├── .gitignore ├── Andromeda ├── Andromeda.php ├── App.php ├── Di.php ├── Di │ ├── FactoryDefault.php │ ├── Injectable.php │ └── InjectionAwareInterface.php ├── DiInterface.php ├── Exception.php ├── Mvc │ ├── Controller.php │ ├── SingletonWriter.php │ └── Writer.php ├── README.md ├── Request.php ├── Response.php └── core │ ├── Controller.class.php │ ├── Loader.class.php │ ├── Log.class.php │ ├── Model.class.php │ ├── Mysql.class.php │ ├── TemplateEngine │ ├── Compile.class.php │ ├── Template.class.php │ ├── cache │ │ └── aa08769cdcb26674c6706093503ff0a3.php │ ├── template │ │ └── member.tpl │ └── test.php │ ├── Util.class.php │ ├── View.class.php │ └── log │ └── driver │ └── File.php ├── App ├── Config │ ├── config.php │ ├── loader.php │ ├── router.php │ └── service.php ├── Controllers │ └── Home │ │ ├── BaseController.class.php │ │ └── IndexController.class.php ├── Models │ └── UserModel.class.php └── Views │ ├── admin │ └── index.html │ └── home │ ├── getUser.html │ ├── getUserById.html │ ├── index.html │ └── var.html ├── Doc └── 实现action的参数获取.md ├── LICENSE ├── Public └── README.md ├── README.md ├── composer.json ├── composer.lock ├── index.php └── test ├── di ├── Di.php └── test.php └── namespace ├── NameSpaceClass.php ├── UseNameSpace.php └── test.php /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Phalcon template 3 | /cache/ 4 | /config/development/ 5 | 6 | .idea/ 7 | App/Log/* 8 | vendor/ -------------------------------------------------------------------------------- /Andromeda/Andromeda.php: -------------------------------------------------------------------------------- 1 | setDI($di); 132 | 133 | 134 | $num = count(self::$s_arr_query); 135 | //echo 'oldNum='.$num; 136 | //取出前3个参数后面的参数组 137 | self::$s_arr_query = array_slice(self::$s_arr_query, 3, $num - 3); 138 | //$controller->$action_name(self::$s_arr_query);// 139 | 140 | $num = count(self::$s_arr_query); 141 | //echo 'newNum='.$num; 142 | /*$str_temp = ''; 143 | foreach (self::$s_arr_query as $key => $value) { 144 | $str_temp = $str_temp . '"'.self::$s_arr_query[$key] . '",'; 145 | } 146 | 147 | Log::write($str_temp); 148 | $str_temp = rtrim($str_temp, ','); 149 | 150 | $fun = '$controller->$action_name(' . $str_temp . ');'; 151 | Log::write($fun); 152 | //$fun='$controller->$action_name(self::$s_arr_query);'; 153 | //echo $fun; 154 | eval($fun);*/ 155 | 156 | //解析有几个参数就组几个参数 157 | //$param=self::getFucntionParameter('$controller->$action_name',self::$s_arr_query); 158 | //Log::write(json_encode(self::$s_arr_query)); 159 | //call_user_func(array($controller_name,$action_name),['p1'=>"2222"],['p2'=>"11111"]); 160 | $reflect = new \ReflectionMethod($controller_name, $action_name); 161 | //处理一下参数 162 | $params=self::bindParams($reflect,self::$s_arr_query); 163 | 164 | $reflect->invokeArgs($controller, $params); 165 | 166 | } 167 | 168 | /** 169 | * 绑定参数 170 | * @param \ReflectionMethod| \ReflectionFunction $reflect 171 | * @param array $vars 172 | * @return array 参数 173 | */ 174 | private static function bindParams($reflect, $vars = []) 175 | { 176 | // 处理post参数 177 | $postParam=Request::instance()->param(); 178 | Log::write("post:".json_encode($postParam)); 179 | 180 | //处理get参数 181 | $args = []; 182 | //反射的方法存在参数 183 | if ($reflect->getNumberOfParameters() > 0) { 184 | //判断数组类型,数字数组时按顺序绑定参数 185 | $params = $reflect->getParameters(); 186 | foreach ($params as $param) { 187 | $args[] = self::getParamValue($param, $postParam); 188 | } 189 | } 190 | 191 | return $args; 192 | } 193 | 194 | 195 | /** 196 | * 设置错误与异常处理 197 | */ 198 | private static function error() 199 | { 200 | error_reporting(E_ALL); 201 | set_error_handler([__CLASS__, 'appError']); 202 | set_exception_handler([__CLASS__, 'appException']); 203 | register_shutdown_function([__CLASS__, 'appShutdown']); 204 | } 205 | 206 | public static function appError() 207 | { 208 | echo '-------error--------'; 209 | $errorArr = error_get_last(); 210 | echo $errorArr['type'] . "
"; 211 | echo $errorArr['message'] . "
"; 212 | } 213 | 214 | /** 215 | * 设置异常处理 216 | * @param Throwable $exception 217 | */ 218 | public static function appException($exception) 219 | { 220 | echo '
'; 221 | echo "----------exception--------
"; 222 | //todo 判断是不是人为抛出的异常,如果是则正常抛,否则都归为系统异常,不向用户暴露错误原因,开启debug模式可以出异常 223 | 224 | 225 | echo "code=" . $exception->getCode() . "
"; 226 | echo "message=" . $exception->getMessage() . "
"; 227 | echo "file=" . $exception->getFile() . "
"; 228 | echo "line=" . $exception->getLine(), "
"; 229 | echo "trace=" . $exception->getTraceAsString() . "
"; 230 | } 231 | 232 | /** 233 | * php脚本无论正常执行完毕或者异常结束都会调用 234 | */ 235 | public static function appShutdown() 236 | { 237 | //echo '****shutdown****'; 238 | } 239 | 240 | /** 241 | * 获取参数值,并判断是否必要参数没填 242 | * @param \ReflectionParameter $param 243 | * @param $vars 244 | * @return array 245 | */ 246 | private static function getParamValue($param, $vars) 247 | { //参数名字 248 | $name = $param->getName(); 249 | //参数的类 250 | $class = $param->getClass(); 251 | 252 | if ($class) { 253 | //todo:参数是个类的情况 254 | return null; 255 | } else { 256 | if (isset($vars[$name])) { 257 | $result = $vars[$name]; 258 | } elseif ($param->isDefaultValueAvailable()) { 259 | $result = $param->getDefaultValue(); 260 | } else { 261 | throw new \InvalidArgumentException("method param is missing:" . $name); 262 | } 263 | } 264 | 265 | return $result; 266 | 267 | 268 | } 269 | 270 | } 271 | 272 | 273 | 274 | 275 | 276 | -------------------------------------------------------------------------------- /Andromeda/App.php: -------------------------------------------------------------------------------- 1 | _sharedInstances[$name] = $definition; 29 | } 30 | 31 | 32 | /** 33 | * 获取共享服务实例 34 | * @param $name :服务名 35 | * @param $param_arr :配置 36 | * @return mixed 37 | * @throws \Exception 38 | */ 39 | public function get($name, $param_arr = null) 40 | { 41 | 42 | $instance = null; 43 | 44 | if (isset($this->_sharedInstances[$name])) { 45 | $definition = $this->_sharedInstances[$name]; 46 | } else { 47 | //去独立服务里面去找 48 | if(isset($this->_services['name'])){ 49 | //找到,new一个新的实例 50 | $instance=new $name; 51 | return $instance; 52 | }else{ 53 | //没找到 54 | throw new \Exception("Service '" . $name . "' wasn't found in the dependency injection container"); 55 | } 56 | 57 | 58 | 59 | } 60 | 61 | if (!is_object($definition)) { 62 | throw new \Exception("Service $name wasn't a object"); 63 | } 64 | 65 | if ($param_arr == null) { 66 | $instance = call_user_func($definition); 67 | } else { 68 | $instance = call_user_func_array($definition, $param_arr); 69 | } 70 | return $instance; 71 | 72 | } 73 | 74 | /* 75 | * 设置独立服务,每次获取的时候会实例化 76 | * @param $name 77 | * @param $definition 78 | */ 79 | public function set($name, $definition) 80 | { 81 | $this->_sharedInstances[$name] = $definition; 82 | $this->_services[$name]=$definition; 83 | } 84 | 85 | public function __construct() 86 | { 87 | return $this; 88 | } 89 | } -------------------------------------------------------------------------------- /Andromeda/Di/Injectable.php: -------------------------------------------------------------------------------- 1 | _dependencyInjector=$dependenceInjector; 28 | } 29 | 30 | public function getDI() 31 | { 32 | return $this->_dependencyInjector; 33 | } 34 | 35 | 36 | public function setEventsManager($eventsManager){ 37 | $this->_eventsManager=$eventsManager; 38 | } 39 | 40 | public function getEventsManager(){ 41 | return $this->_eventsManager; 42 | } 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | } -------------------------------------------------------------------------------- /Andromeda/Di/InjectionAwareInterface.php: -------------------------------------------------------------------------------- 1 | data[$label] = $data; 38 | } 39 | 40 | /** 41 | * 获取异常额外Debug数据 42 | * 主要用于输出到异常页面便于调试 43 | * @return array 由setData设置的Debug数据 44 | */ 45 | final public function getData() 46 | { 47 | return $this->data; 48 | } 49 | } -------------------------------------------------------------------------------- /Andromeda/Mvc/Controller.php: -------------------------------------------------------------------------------- 1 | _dependencyInjector->_sharedInstances[$name])) { 25 | $definition = $this->_dependencyInjector->_sharedInstances[$name]; 26 | } else { 27 | throw new \Exception("Service '" . $name . "' wasn't found in the dependency injection container"); 28 | } 29 | 30 | if (is_object($definition)) { 31 | $instance = call_user_func($definition); 32 | } 33 | return $instance; 34 | 35 | } 36 | 37 | 38 | public function __construct($di=null) 39 | { 40 | //$this->loader=new \Loader(); 41 | $this->view=new \View(); 42 | $this->_dependencyInjector=$di; 43 | } 44 | 45 | 46 | 47 | 48 | public function redirect($url,$message,$wait=0){ 49 | if($wait=0){ 50 | header("Location:$url"); 51 | 52 | }else{ 53 | include CURR_VIEW_PATH."message.html"; 54 | 55 | } 56 | exit; 57 | 58 | } 59 | 60 | protected function assign($name,$value='') { 61 | $this->view->assign($name,$value); 62 | return $this; 63 | } 64 | 65 | protected function display($template){ 66 | $this->view->display(CURR_VIEW_PATH.$template); 67 | 68 | } 69 | 70 | /** 71 | * 浏览器友好的变量输出 72 | * @param mixed $var 变量 73 | * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串 74 | * @param string $label 标签 默认为空 75 | * @param boolean $strict 是否严谨 默认为true 76 | * @return void|string 77 | */ 78 | protected function dump($var, $echo=true, $label=null, $strict=true) { 79 | $label = ($label === null) ? '' : rtrim($label) . ' '; 80 | if (!$strict) { 81 | if (ini_get('html_errors')) { 82 | $output = print_r($var, true); 83 | $output = '
' . $label . htmlspecialchars($output, ENT_QUOTES) . '
'; 84 | } else { 85 | $output = $label . print_r($var, true); 86 | } 87 | } else { 88 | ob_start(); 89 | var_dump($var); 90 | $output = ob_get_clean(); 91 | if (!extension_loaded('xdebug')) { 92 | $output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output); 93 | $output = '
' . $label . htmlspecialchars($output, ENT_QUOTES) . '
'; 94 | } 95 | } 96 | if ($echo) { 97 | echo($output); 98 | return null; 99 | }else 100 | return $output; 101 | } 102 | 103 | 104 | } 105 | 106 | -------------------------------------------------------------------------------- /Andromeda/Mvc/SingletonWriter.php: -------------------------------------------------------------------------------- 1 | "; 27 | } 28 | 29 | public static function getInstance($di) 30 | { 31 | if (!self::$singletonWriter) { 32 | self::$singletonWriter = new self($di); 33 | } 34 | return self::$singletonWriter; 35 | } 36 | 37 | /** 38 | * 在浏览器输出一些内容 39 | * @param $content 40 | */ 41 | public function write($content) 42 | { 43 | echo "SingletonWriter write $content"; 44 | } 45 | 46 | public function hello() 47 | { 48 | echo "SingletonWriter hello guys
"; 49 | } 50 | 51 | public static function staticHello() 52 | { 53 | echo "SingletonWriter static hello guys
"; 54 | } 55 | 56 | public function setDI($di) 57 | { 58 | // TODO: Implement setDI() method. 59 | } 60 | 61 | public function getDI() 62 | { 63 | // TODO: Implement getDI() method. 64 | } 65 | } -------------------------------------------------------------------------------- /Andromeda/Mvc/Writer.php: -------------------------------------------------------------------------------- 1 | "; 22 | } 23 | 24 | /** 25 | * 在浏览器输出一些内容 26 | * @param $content 27 | */ 28 | public function write($content){ 29 | echo "write $content
"; 30 | } 31 | 32 | public function hello(){ 33 | echo "hello guys
"; 34 | } 35 | 36 | public function setDI($di) 37 | { 38 | // TODO: Implement setDI() method. 39 | } 40 | 41 | public function getDI() 42 | { 43 | // TODO: Implement getDI() method. 44 | } 45 | } -------------------------------------------------------------------------------- /Andromeda/README.md: -------------------------------------------------------------------------------- 1 | 框架目录 2 | -------------------------------------------------------------------------------- /Andromeda/Request.php: -------------------------------------------------------------------------------- 1 | 'application/xml,text/xml,application/x-xml', 89 | 'json' => 'application/json,text/x-json,application/jsonrequest,text/json', 90 | 'js' => 'text/javascript,application/javascript,application/x-javascript', 91 | 'css' => 'text/css', 92 | 'rss' => 'application/rss+xml', 93 | 'yaml' => 'application/x-yaml,text/yaml', 94 | 'atom' => 'application/atom+xml', 95 | 'pdf' => 'application/pdf', 96 | 'text' => 'text/plain', 97 | 'image' => 'image/png,image/jpg,image/jpeg,image/pjpeg,image/gif,image/webp,image/*', 98 | 'csv' => 'text/csv', 99 | 'html' => 'text/html,application/xhtml+xml,*/*', 100 | ]; 101 | 102 | protected $content; 103 | 104 | // 全局过滤规则 105 | protected $filter; 106 | // Hook扩展方法 107 | protected static $hook = []; 108 | // 绑定的属性 109 | protected $bind = []; 110 | // php://input 111 | protected $input; 112 | // 请求缓存 113 | protected $cache; 114 | // 缓存是否检查 115 | protected $isCheckCache; 116 | 117 | /** 118 | * 构造函数 119 | * @access protected 120 | * @param array $options 参数 121 | */ 122 | protected function __construct($options = []) 123 | { 124 | foreach ($options as $name => $item) { 125 | if (property_exists($this, $name)) { 126 | $this->$name = $item; 127 | } 128 | } 129 | 130 | // 保存 php://input 131 | $this->input = file_get_contents('php://input'); 132 | } 133 | 134 | public function __call($method, $args) 135 | { 136 | if (array_key_exists($method, self::$hook)) { 137 | array_unshift($args, $this); 138 | return call_user_func_array(self::$hook[$method], $args); 139 | } else { 140 | throw new Exception('method not exists:' . __CLASS__ . '->' . $method); 141 | } 142 | } 143 | 144 | /** 145 | * Hook 方法注入 146 | * @access public 147 | * @param string|array $method 方法名 148 | * @param mixed $callback callable 149 | * @return void 150 | */ 151 | public static function hook($method, $callback = null) 152 | { 153 | if (is_array($method)) { 154 | self::$hook = array_merge(self::$hook, $method); 155 | } else { 156 | self::$hook[$method] = $callback; 157 | } 158 | } 159 | 160 | /** 161 | * 初始化 162 | * @access public 163 | * @param array $options 参数 164 | * @return Request 165 | */ 166 | public static function instance($options = []) 167 | { 168 | if (is_null(self::$instance)) { 169 | self::$instance = new static($options); 170 | } 171 | return self::$instance; 172 | } 173 | 174 | /** 175 | * 创建一个URL请求 176 | * @access public 177 | * @param string $uri URL地址 178 | * @param string $method 请求类型 179 | * @param array $params 请求参数 180 | * @param array $cookie 181 | * @param array $files 182 | * @param array $server 183 | * @param string $content 184 | * @return \Request 185 | */ 186 | public static function create($uri, $method = 'GET', $params = [], $cookie = [], $files = [], $server = [], $content = null) 187 | { 188 | $server['PATH_INFO'] = ''; 189 | $server['REQUEST_METHOD'] = strtoupper($method); 190 | $info = parse_url($uri); 191 | if (isset($info['host'])) { 192 | $server['SERVER_NAME'] = $info['host']; 193 | $server['HTTP_HOST'] = $info['host']; 194 | } 195 | if (isset($info['scheme'])) { 196 | if ('https' === $info['scheme']) { 197 | $server['HTTPS'] = 'on'; 198 | $server['SERVER_PORT'] = 443; 199 | } else { 200 | unset($server['HTTPS']); 201 | $server['SERVER_PORT'] = 80; 202 | } 203 | } 204 | if (isset($info['port'])) { 205 | $server['SERVER_PORT'] = $info['port']; 206 | $server['HTTP_HOST'] = $server['HTTP_HOST'] . ':' . $info['port']; 207 | } 208 | if (isset($info['user'])) { 209 | $server['PHP_AUTH_USER'] = $info['user']; 210 | } 211 | if (isset($info['pass'])) { 212 | $server['PHP_AUTH_PW'] = $info['pass']; 213 | } 214 | if (!isset($info['path'])) { 215 | $info['path'] = '/'; 216 | } 217 | $options = []; 218 | $options[strtolower($method)] = $params; 219 | $queryString = ''; 220 | if (isset($info['query'])) { 221 | parse_str(html_entity_decode($info['query']), $query); 222 | if (!empty($params)) { 223 | $params = array_replace($query, $params); 224 | $queryString = http_build_query($query, '', '&'); 225 | } else { 226 | $params = $query; 227 | $queryString = $info['query']; 228 | } 229 | } elseif (!empty($params)) { 230 | $queryString = http_build_query($params, '', '&'); 231 | } 232 | if ($queryString) { 233 | parse_str($queryString, $get); 234 | $options['get'] = isset($options['get']) ? array_merge($get, $options['get']) : $get; 235 | } 236 | 237 | $server['REQUEST_URI'] = $info['path'] . ('' !== $queryString ? '?' . $queryString : ''); 238 | $server['QUERY_STRING'] = $queryString; 239 | $options['cookie'] = $cookie; 240 | $options['param'] = $params; 241 | $options['file'] = $files; 242 | $options['server'] = $server; 243 | $options['url'] = $server['REQUEST_URI']; 244 | $options['baseUrl'] = $info['path']; 245 | $options['pathinfo'] = '/' == $info['path'] ? '/' : ltrim($info['path'], '/'); 246 | $options['method'] = $server['REQUEST_METHOD']; 247 | $options['domain'] = isset($info['scheme']) ? $info['scheme'] . '://' . $server['HTTP_HOST'] : ''; 248 | $options['content'] = $content; 249 | self::$instance = new self($options); 250 | return self::$instance; 251 | } 252 | 253 | /** 254 | * 设置或获取当前包含协议的域名 255 | * @access public 256 | * @param string $domain 域名 257 | * @return string 258 | */ 259 | public function domain($domain = null) 260 | { 261 | if (!is_null($domain)) { 262 | $this->domain = $domain; 263 | return $this; 264 | } elseif (!$this->domain) { 265 | $this->domain = $this->scheme() . '://' . $this->host(); 266 | } 267 | return $this->domain; 268 | } 269 | 270 | /** 271 | * 设置或获取当前完整URL 包括QUERY_STRING 272 | * @access public 273 | * @param string|true $url URL地址 true 带域名获取 274 | * @return string 275 | */ 276 | public function url($url = null) 277 | { 278 | if (!is_null($url) && true !== $url) { 279 | $this->url = $url; 280 | return $this; 281 | } elseif (!$this->url) { 282 | if (IS_CLI) { 283 | $this->url = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : ''; 284 | } elseif (isset($_SERVER['HTTP_X_REWRITE_URL'])) { 285 | $this->url = $_SERVER['HTTP_X_REWRITE_URL']; 286 | } elseif (isset($_SERVER['REQUEST_URI'])) { 287 | $this->url = $_SERVER['REQUEST_URI']; 288 | } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { 289 | $this->url = $_SERVER['ORIG_PATH_INFO'] . (!empty($_SERVER['QUERY_STRING']) ? '?' . $_SERVER['QUERY_STRING'] : ''); 290 | } else { 291 | $this->url = ''; 292 | } 293 | } 294 | return true === $url ? $this->domain() . $this->url : $this->url; 295 | } 296 | 297 | /** 298 | * 设置或获取当前URL 不含QUERY_STRING 299 | * @access public 300 | * @param string $url URL地址 301 | * @return string 302 | */ 303 | public function baseUrl($url = null) 304 | { 305 | if (!is_null($url) && true !== $url) { 306 | $this->baseUrl = $url; 307 | return $this; 308 | } elseif (!$this->baseUrl) { 309 | $str = $this->url(); 310 | $this->baseUrl = strpos($str, '?') ? strstr($str, '?', true) : $str; 311 | } 312 | return true === $url ? $this->domain() . $this->baseUrl : $this->baseUrl; 313 | } 314 | 315 | /** 316 | * 设置或获取当前执行的文件 SCRIPT_NAME 317 | * @access public 318 | * @param string $file 当前执行的文件 319 | * @return string 320 | */ 321 | public function baseFile($file = null) 322 | { 323 | if (!is_null($file) && true !== $file) { 324 | $this->baseFile = $file; 325 | return $this; 326 | } elseif (!$this->baseFile) { 327 | $url = ''; 328 | if (!IS_CLI) { 329 | $script_name = basename($_SERVER['SCRIPT_FILENAME']); 330 | if (basename($_SERVER['SCRIPT_NAME']) === $script_name) { 331 | $url = $_SERVER['SCRIPT_NAME']; 332 | } elseif (basename($_SERVER['PHP_SELF']) === $script_name) { 333 | $url = $_SERVER['PHP_SELF']; 334 | } elseif (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $script_name) { 335 | $url = $_SERVER['ORIG_SCRIPT_NAME']; 336 | } elseif (($pos = strpos($_SERVER['PHP_SELF'], '/' . $script_name)) !== false) { 337 | $url = substr($_SERVER['SCRIPT_NAME'], 0, $pos) . '/' . $script_name; 338 | } elseif (isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'], $_SERVER['DOCUMENT_ROOT']) === 0) { 339 | $url = str_replace('\\', '/', str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME'])); 340 | } 341 | } 342 | $this->baseFile = $url; 343 | } 344 | return true === $file ? $this->domain() . $this->baseFile : $this->baseFile; 345 | } 346 | 347 | /** 348 | * 设置或获取URL访问根地址 349 | * @access public 350 | * @param string $url URL地址 351 | * @return string 352 | */ 353 | public function root($url = null) 354 | { 355 | if (!is_null($url) && true !== $url) { 356 | $this->root = $url; 357 | return $this; 358 | } elseif (!$this->root) { 359 | $file = $this->baseFile(); 360 | if ($file && 0 !== strpos($this->url(), $file)) { 361 | $file = str_replace('\\', '/', dirname($file)); 362 | } 363 | $this->root = rtrim($file, '/'); 364 | } 365 | return true === $url ? $this->domain() . $this->root : $this->root; 366 | } 367 | 368 | /** 369 | * 获取当前请求URL的pathinfo信息(含URL后缀) 370 | * @access public 371 | * @return string 372 | */ 373 | public function pathinfo() 374 | { 375 | if (is_null($this->pathinfo)) { 376 | if (isset($_GET[Config::get('var_pathinfo')])) { 377 | // 判断URL里面是否有兼容模式参数 378 | $_SERVER['PATH_INFO'] = $_GET[Config::get('var_pathinfo')]; 379 | unset($_GET[Config::get('var_pathinfo')]); 380 | } elseif (IS_CLI) { 381 | // CLI模式下 index.php module/controller/action/params/... 382 | $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : ''; 383 | } 384 | 385 | // 分析PATHINFO信息 386 | if (!isset($_SERVER['PATH_INFO'])) { 387 | foreach (Config::get('pathinfo_fetch') as $type) { 388 | if (!empty($_SERVER[$type])) { 389 | $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ? 390 | substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type]; 391 | break; 392 | } 393 | } 394 | } 395 | $this->pathinfo = empty($_SERVER['PATH_INFO']) ? '/' : ltrim($_SERVER['PATH_INFO'], '/'); 396 | } 397 | return $this->pathinfo; 398 | } 399 | 400 | /** 401 | * 获取当前请求URL的pathinfo信息(不含URL后缀) 402 | * @access public 403 | * @return string 404 | */ 405 | public function path() 406 | { 407 | if (is_null($this->path)) { 408 | $suffix = Config::get('url_html_suffix'); 409 | $pathinfo = $this->pathinfo(); 410 | if (false === $suffix) { 411 | // 禁止伪静态访问 412 | $this->path = $pathinfo; 413 | } elseif ($suffix) { 414 | // 去除正常的URL后缀 415 | $this->path = preg_replace('/\.(' . ltrim($suffix, '.') . ')$/i', '', $pathinfo); 416 | } else { 417 | // 允许任何后缀访问 418 | $this->path = preg_replace('/\.' . $this->ext() . '$/i', '', $pathinfo); 419 | } 420 | } 421 | return $this->path; 422 | } 423 | 424 | /** 425 | * 当前URL的访问后缀 426 | * @access public 427 | * @return string 428 | */ 429 | public function ext() 430 | { 431 | return pathinfo($this->pathinfo(), PATHINFO_EXTENSION); 432 | } 433 | 434 | /** 435 | * 获取当前请求的时间 436 | * @access public 437 | * @param bool $float 是否使用浮点类型 438 | * @return integer|float 439 | */ 440 | public function time($float = false) 441 | { 442 | return $float ? $_SERVER['REQUEST_TIME_FLOAT'] : $_SERVER['REQUEST_TIME']; 443 | } 444 | 445 | /** 446 | * 当前请求的资源类型 447 | * @access public 448 | * @return false|string 449 | */ 450 | public function type() 451 | { 452 | $accept = $this->server('HTTP_ACCEPT'); 453 | if (empty($accept)) { 454 | return false; 455 | } 456 | 457 | foreach ($this->mimeType as $key => $val) { 458 | $array = explode(',', $val); 459 | foreach ($array as $k => $v) { 460 | if (stristr($accept, $v)) { 461 | return $key; 462 | } 463 | } 464 | } 465 | return false; 466 | } 467 | 468 | /** 469 | * 设置资源类型 470 | * @access public 471 | * @param string|array $type 资源类型名 472 | * @param string $val 资源类型 473 | * @return void 474 | */ 475 | public function mimeType($type, $val = '') 476 | { 477 | if (is_array($type)) { 478 | $this->mimeType = array_merge($this->mimeType, $type); 479 | } else { 480 | $this->mimeType[$type] = $val; 481 | } 482 | } 483 | 484 | /** 485 | * 当前的请求类型 486 | * @access public 487 | * @param bool $method true 获取原始请求类型 488 | * @return string 489 | */ 490 | public function method($method = false) 491 | { 492 | if (true === $method) { 493 | // 获取原始请求类型 494 | return IS_CLI ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']); 495 | } elseif (!$this->method) { 496 | if (isset($_POST[Config::get('var_method')])) { 497 | $this->method = strtoupper($_POST[Config::get('var_method')]); 498 | $this->{$this->method}($_POST); 499 | } elseif (isset($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE'])) { 500 | $this->method = strtoupper($_SERVER['HTTP_X_HTTP_METHOD_OVERRIDE']); 501 | } else { 502 | $this->method = IS_CLI ? 'GET' : (isset($this->server['REQUEST_METHOD']) ? $this->server['REQUEST_METHOD'] : $_SERVER['REQUEST_METHOD']); 503 | } 504 | } 505 | return $this->method; 506 | } 507 | 508 | /** 509 | * 是否为GET请求 510 | * @access public 511 | * @return bool 512 | */ 513 | public function isGet() 514 | { 515 | return $this->method() == 'GET'; 516 | } 517 | 518 | /** 519 | * 是否为POST请求 520 | * @access public 521 | * @return bool 522 | */ 523 | public function isPost() 524 | { 525 | return $this->method() == 'POST'; 526 | } 527 | 528 | /** 529 | * 是否为PUT请求 530 | * @access public 531 | * @return bool 532 | */ 533 | public function isPut() 534 | { 535 | return $this->method() == 'PUT'; 536 | } 537 | 538 | /** 539 | * 是否为DELTE请求 540 | * @access public 541 | * @return bool 542 | */ 543 | public function isDelete() 544 | { 545 | return $this->method() == 'DELETE'; 546 | } 547 | 548 | /** 549 | * 是否为HEAD请求 550 | * @access public 551 | * @return bool 552 | */ 553 | public function isHead() 554 | { 555 | return $this->method() == 'HEAD'; 556 | } 557 | 558 | /** 559 | * 是否为PATCH请求 560 | * @access public 561 | * @return bool 562 | */ 563 | public function isPatch() 564 | { 565 | return $this->method() == 'PATCH'; 566 | } 567 | 568 | /** 569 | * 是否为OPTIONS请求 570 | * @access public 571 | * @return bool 572 | */ 573 | public function isOptions() 574 | { 575 | return $this->method() == 'OPTIONS'; 576 | } 577 | 578 | /** 579 | * 是否为cli 580 | * @access public 581 | * @return bool 582 | */ 583 | public function isCli() 584 | { 585 | return PHP_SAPI == 'cli'; 586 | } 587 | 588 | /** 589 | * 是否为cgi 590 | * @access public 591 | * @return bool 592 | */ 593 | public function isCgi() 594 | { 595 | return strpos(PHP_SAPI, 'cgi') === 0; 596 | } 597 | 598 | /** 599 | * 获取当前请求的参数 600 | * @access public 601 | * @param string|array $name 变量名 602 | * @param mixed $default 默认值 603 | * @param string|array $filter 过滤方法 604 | * @return mixed 605 | */ 606 | public function param($name = '', $default = null, $filter = '') 607 | { 608 | if (empty($this->param)) { 609 | $method = $this->method(true); 610 | // 自动获取请求变量 611 | switch ($method) { 612 | case 'POST': 613 | $vars = $this->post(false); 614 | break; 615 | case 'PUT': 616 | case 'DELETE': 617 | case 'PATCH': 618 | $vars = $this->put(false); 619 | break; 620 | default: 621 | $vars = []; 622 | } 623 | // 当前请求参数和URL地址中的参数合并 624 | $this->param = array_merge($this->get(false), $vars, $this->route(false)); 625 | } 626 | if (true === $name) { 627 | // 获取包含文件上传信息的数组 628 | $file = $this->file(); 629 | $data = is_array($file) ? array_merge($this->param, $file) : $this->param; 630 | return $this->input($data, '', $default, $filter); 631 | } 632 | return $this->input($this->param, $name, $default, $filter); 633 | } 634 | 635 | /** 636 | * 设置获取路由参数 637 | * @access public 638 | * @param string|array $name 变量名 639 | * @param mixed $default 默认值 640 | * @param string|array $filter 过滤方法 641 | * @return mixed 642 | */ 643 | public function route($name = '', $default = null, $filter = '') 644 | { 645 | if (is_array($name)) { 646 | $this->param = []; 647 | return $this->route = array_merge($this->route, $name); 648 | } 649 | return $this->input($this->route, $name, $default, $filter); 650 | } 651 | 652 | /** 653 | * 设置获取GET参数 654 | * @access public 655 | * @param string|array $name 变量名 656 | * @param mixed $default 默认值 657 | * @param string|array $filter 过滤方法 658 | * @return mixed 659 | */ 660 | public function get($name = '', $default = null, $filter = '') 661 | { 662 | if (empty($this->get)) { 663 | $this->get = $_GET; 664 | } 665 | if (is_array($name)) { 666 | $this->param = []; 667 | return $this->get = array_merge($this->get, $name); 668 | } 669 | return $this->input($this->get, $name, $default, $filter); 670 | } 671 | 672 | /** 673 | * 设置获取POST参数 674 | * @access public 675 | * @param string $name 变量名 676 | * @param mixed $default 默认值 677 | * @param string|array $filter 过滤方法 678 | * @return mixed 679 | */ 680 | public function post($name = '', $default = null, $filter = '') 681 | { 682 | if (empty($this->post)) { 683 | $content = $this->input; 684 | if (empty($_POST) && false !== strpos($this->contentType(), 'application/json')) { 685 | $this->post = (array) json_decode($content, true); 686 | } else { 687 | $this->post = $_POST; 688 | } 689 | } 690 | if (is_array($name)) { 691 | $this->param = []; 692 | return $this->post = array_merge($this->post, $name); 693 | } 694 | return $this->input($this->post, $name, $default, $filter); 695 | } 696 | 697 | /** 698 | * 设置获取PUT参数 699 | * @access public 700 | * @param string|array $name 变量名 701 | * @param mixed $default 默认值 702 | * @param string|array $filter 过滤方法 703 | * @return mixed 704 | */ 705 | public function put($name = '', $default = null, $filter = '') 706 | { 707 | if (is_null($this->put)) { 708 | $content = $this->input; 709 | if (false !== strpos($this->contentType(), 'application/json')) { 710 | $this->put = (array) json_decode($content, true); 711 | } else { 712 | parse_str($content, $this->put); 713 | } 714 | } 715 | if (is_array($name)) { 716 | $this->param = []; 717 | return $this->put = is_null($this->put) ? $name : array_merge($this->put, $name); 718 | } 719 | 720 | return $this->input($this->put, $name, $default, $filter); 721 | } 722 | 723 | /** 724 | * 设置获取DELETE参数 725 | * @access public 726 | * @param string|array $name 变量名 727 | * @param mixed $default 默认值 728 | * @param string|array $filter 过滤方法 729 | * @return mixed 730 | */ 731 | public function delete($name = '', $default = null, $filter = '') 732 | { 733 | return $this->put($name, $default, $filter); 734 | } 735 | 736 | /** 737 | * 设置获取PATCH参数 738 | * @access public 739 | * @param string|array $name 变量名 740 | * @param mixed $default 默认值 741 | * @param string|array $filter 过滤方法 742 | * @return mixed 743 | */ 744 | public function patch($name = '', $default = null, $filter = '') 745 | { 746 | return $this->put($name, $default, $filter); 747 | } 748 | 749 | /** 750 | * 获取request变量 751 | * @param string $name 数据名称 752 | * @param string $default 默认值 753 | * @param string|array $filter 过滤方法 754 | * @return mixed 755 | */ 756 | public function request($name = '', $default = null, $filter = '') 757 | { 758 | if (empty($this->request)) { 759 | $this->request = $_REQUEST; 760 | } 761 | if (is_array($name)) { 762 | $this->param = []; 763 | return $this->request = array_merge($this->request, $name); 764 | } 765 | return $this->input($this->request, $name, $default, $filter); 766 | } 767 | 768 | /** 769 | * 获取session数据 770 | * @access public 771 | * @param string|array $name 数据名称 772 | * @param string $default 默认值 773 | * @param string|array $filter 过滤方法 774 | * @return mixed 775 | */ 776 | public function session($name = '', $default = null, $filter = '') 777 | { 778 | if (empty($this->session)) { 779 | $this->session = Session::get(); 780 | } 781 | if (is_array($name)) { 782 | return $this->session = array_merge($this->session, $name); 783 | } 784 | return $this->input($this->session, $name, $default, $filter); 785 | } 786 | 787 | /** 788 | * 获取cookie参数 789 | * @access public 790 | * @param string|array $name 数据名称 791 | * @param string $default 默认值 792 | * @param string|array $filter 过滤方法 793 | * @return mixed 794 | */ 795 | public function cookie($name = '', $default = null, $filter = '') 796 | { 797 | if (empty($this->cookie)) { 798 | $this->cookie = Cookie::get(); 799 | } 800 | if (is_array($name)) { 801 | return $this->cookie = array_merge($this->cookie, $name); 802 | } elseif (!empty($name)) { 803 | $data = Cookie::has($name) ? Cookie::get($name) : $default; 804 | } else { 805 | $data = $this->cookie; 806 | } 807 | 808 | // 解析过滤器 809 | $filter = $this->getFilter($filter, $default); 810 | 811 | if (is_array($data)) { 812 | array_walk_recursive($data, [$this, 'filterValue'], $filter); 813 | reset($data); 814 | } else { 815 | $this->filterValue($data, $name, $filter); 816 | } 817 | return $data; 818 | } 819 | 820 | /** 821 | * 获取server参数 822 | * @access public 823 | * @param string|array $name 数据名称 824 | * @param string $default 默认值 825 | * @param string|array $filter 过滤方法 826 | * @return mixed 827 | */ 828 | public function server($name = '', $default = null, $filter = '') 829 | { 830 | if (empty($this->server)) { 831 | $this->server = $_SERVER; 832 | } 833 | if (is_array($name)) { 834 | return $this->server = array_merge($this->server, $name); 835 | } 836 | return $this->input($this->server, false === $name ? false : strtoupper($name), $default, $filter); 837 | } 838 | 839 | /** 840 | * 获取上传的文件信息 841 | * @access public 842 | * @param string|array $name 名称 843 | * @return null|array|\File 844 | */ 845 | public function file($name = '') 846 | { 847 | if (empty($this->file)) { 848 | $this->file = isset($_FILES) ? $_FILES : []; 849 | } 850 | if (is_array($name)) { 851 | return $this->file = array_merge($this->file, $name); 852 | } 853 | $files = $this->file; 854 | if (!empty($files)) { 855 | // 处理上传文件 856 | $array = []; 857 | foreach ($files as $key => $file) { 858 | if (is_array($file['name'])) { 859 | $item = []; 860 | $keys = array_keys($file); 861 | $count = count($file['name']); 862 | for ($i = 0; $i < $count; $i++) { 863 | if (empty($file['tmp_name'][$i]) || !is_file($file['tmp_name'][$i])) { 864 | continue; 865 | } 866 | $temp['key'] = $key; 867 | foreach ($keys as $_key) { 868 | $temp[$_key] = $file[$_key][$i]; 869 | } 870 | $item[] = (new File($temp['tmp_name']))->setUploadInfo($temp); 871 | } 872 | $array[$key] = $item; 873 | } else { 874 | if ($file instanceof File) { 875 | $array[$key] = $file; 876 | } else { 877 | if (empty($file['tmp_name']) || !is_file($file['tmp_name'])) { 878 | continue; 879 | } 880 | $array[$key] = (new File($file['tmp_name']))->setUploadInfo($file); 881 | } 882 | } 883 | } 884 | if (strpos($name, '.')) { 885 | list($name, $sub) = explode('.', $name); 886 | } 887 | if ('' === $name) { 888 | // 获取全部文件 889 | return $array; 890 | } elseif (isset($sub) && isset($array[$name][$sub])) { 891 | return $array[$name][$sub]; 892 | } elseif (isset($array[$name])) { 893 | return $array[$name]; 894 | } 895 | } 896 | return; 897 | } 898 | 899 | /** 900 | * 获取环境变量 901 | * @param string|array $name 数据名称 902 | * @param string $default 默认值 903 | * @param string|array $filter 过滤方法 904 | * @return mixed 905 | */ 906 | public function env($name = '', $default = null, $filter = '') 907 | { 908 | if (empty($this->env)) { 909 | $this->env = $_ENV; 910 | } 911 | if (is_array($name)) { 912 | return $this->env = array_merge($this->env, $name); 913 | } 914 | return $this->input($this->env, false === $name ? false : strtoupper($name), $default, $filter); 915 | } 916 | 917 | /** 918 | * 设置或者获取当前的Header 919 | * @access public 920 | * @param string|array $name header名称 921 | * @param string $default 默认值 922 | * @return string 923 | */ 924 | public function header($name = '', $default = null) 925 | { 926 | if (empty($this->header)) { 927 | $header = []; 928 | if (function_exists('apache_request_headers') && $result = apache_request_headers()) { 929 | $header = $result; 930 | } else { 931 | $server = $this->server ?: $_SERVER; 932 | foreach ($server as $key => $val) { 933 | if (0 === strpos($key, 'HTTP_')) { 934 | $key = str_replace('_', '-', strtolower(substr($key, 5))); 935 | $header[$key] = $val; 936 | } 937 | } 938 | if (isset($server['CONTENT_TYPE'])) { 939 | $header['content-type'] = $server['CONTENT_TYPE']; 940 | } 941 | if (isset($server['CONTENT_LENGTH'])) { 942 | $header['content-length'] = $server['CONTENT_LENGTH']; 943 | } 944 | } 945 | $this->header = array_change_key_case($header); 946 | } 947 | if (is_array($name)) { 948 | return $this->header = array_merge($this->header, $name); 949 | } 950 | if ('' === $name) { 951 | return $this->header; 952 | } 953 | $name = str_replace('_', '-', strtolower($name)); 954 | return isset($this->header[$name]) ? $this->header[$name] : $default; 955 | } 956 | 957 | /** 958 | * 获取变量 支持过滤和默认值 959 | * @param array $data 数据源 960 | * @param string|false $name 字段名 961 | * @param mixed $default 默认值 962 | * @param string|array $filter 过滤函数 963 | * @return mixed 964 | */ 965 | public function input($data = [], $name = '', $default = null, $filter = '') 966 | { 967 | if (false === $name) { 968 | // 获取原始数据 969 | return $data; 970 | } 971 | $name = (string) $name; 972 | if ('' != $name) { 973 | // 解析name 974 | if (strpos($name, '/')) { 975 | list($name, $type) = explode('/', $name); 976 | } else { 977 | $type = 's'; 978 | } 979 | // 按.拆分成多维数组进行判断 980 | foreach (explode('.', $name) as $val) { 981 | if (isset($data[$val])) { 982 | $data = $data[$val]; 983 | } else { 984 | // 无输入数据,返回默认值 985 | return $default; 986 | } 987 | } 988 | if (is_object($data)) { 989 | return $data; 990 | } 991 | } 992 | 993 | // 解析过滤器 994 | $filter = $this->getFilter($filter, $default); 995 | 996 | if (is_array($data)) { 997 | array_walk_recursive($data, [$this, 'filterValue'], $filter); 998 | reset($data); 999 | } else { 1000 | $this->filterValue($data, $name, $filter); 1001 | } 1002 | 1003 | if (isset($type) && $data !== $default) { 1004 | // 强制类型转换 1005 | $this->typeCast($data, $type); 1006 | } 1007 | return $data; 1008 | } 1009 | 1010 | /** 1011 | * 设置或获取当前的过滤规则 1012 | * @param mixed $filter 过滤规则 1013 | * @return mixed 1014 | */ 1015 | public function filter($filter = null) 1016 | { 1017 | if (is_null($filter)) { 1018 | return $this->filter; 1019 | } else { 1020 | $this->filter = $filter; 1021 | } 1022 | } 1023 | 1024 | protected function getFilter($filter, $default) 1025 | { 1026 | if (is_null($filter)) { 1027 | $filter = []; 1028 | } else { 1029 | $filter = $filter ?: $this->filter; 1030 | if (is_string($filter) && false === strpos($filter, '/')) { 1031 | $filter = explode(',', $filter); 1032 | } else { 1033 | $filter = (array) $filter; 1034 | } 1035 | } 1036 | 1037 | $filter[] = $default; 1038 | return $filter; 1039 | } 1040 | 1041 | /** 1042 | * 递归过滤给定的值 1043 | * @param mixed $value 键值 1044 | * @param mixed $key 键名 1045 | * @param array $filters 过滤方法+默认值 1046 | * @return mixed 1047 | */ 1048 | private function filterValue(&$value, $key, $filters) 1049 | { 1050 | $default = array_pop($filters); 1051 | foreach ($filters as $filter) { 1052 | if (is_callable($filter)) { 1053 | // 调用函数或者方法过滤 1054 | $value = call_user_func($filter, $value); 1055 | } elseif (is_scalar($value)) { 1056 | if (false !== strpos($filter, '/')) { 1057 | // 正则过滤 1058 | if (!preg_match($filter, $value)) { 1059 | // 匹配不成功返回默认值 1060 | $value = $default; 1061 | break; 1062 | } 1063 | } elseif (!empty($filter)) { 1064 | // filter函数不存在时, 则使用filter_var进行过滤 1065 | // filter为非整形值时, 调用filter_id取得过滤id 1066 | $value = filter_var($value, is_int($filter) ? $filter : filter_id($filter)); 1067 | if (false === $value) { 1068 | $value = $default; 1069 | break; 1070 | } 1071 | } 1072 | } 1073 | } 1074 | return $this->filterExp($value); 1075 | } 1076 | 1077 | /** 1078 | * 过滤表单中的表达式 1079 | * @param string $value 1080 | * @return void 1081 | */ 1082 | public function filterExp(&$value) 1083 | { 1084 | // 过滤查询特殊字符 1085 | if (is_string($value) && preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|XOR|LIKE|NOTLIKE|NOT LIKE|NOT BETWEEN|NOTBETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i', $value)) { 1086 | $value .= ' '; 1087 | } 1088 | // TODO 其他安全过滤 1089 | } 1090 | 1091 | /** 1092 | * 强制类型转换 1093 | * @param string $data 1094 | * @param string $type 1095 | * @return mixed 1096 | */ 1097 | private function typeCast(&$data, $type) 1098 | { 1099 | switch (strtolower($type)) { 1100 | // 数组 1101 | case 'a': 1102 | $data = (array) $data; 1103 | break; 1104 | // 数字 1105 | case 'd': 1106 | $data = (int) $data; 1107 | break; 1108 | // 浮点 1109 | case 'f': 1110 | $data = (float) $data; 1111 | break; 1112 | // 布尔 1113 | case 'b': 1114 | $data = (boolean) $data; 1115 | break; 1116 | // 字符串 1117 | case 's': 1118 | default: 1119 | if (is_scalar($data)) { 1120 | $data = (string) $data; 1121 | } else { 1122 | throw new \InvalidArgumentException('variable type error:' . gettype($data)); 1123 | } 1124 | } 1125 | } 1126 | 1127 | /** 1128 | * 是否存在某个请求参数 1129 | * @access public 1130 | * @param string $name 变量名 1131 | * @param string $type 变量类型 1132 | * @param bool $checkEmpty 是否检测空值 1133 | * @return mixed 1134 | */ 1135 | public function has($name, $type = 'param', $checkEmpty = false) 1136 | { 1137 | if (empty($this->$type)) { 1138 | $param = $this->$type(); 1139 | } else { 1140 | $param = $this->$type; 1141 | } 1142 | // 按.拆分成多维数组进行判断 1143 | foreach (explode('.', $name) as $val) { 1144 | if (isset($param[$val])) { 1145 | $param = $param[$val]; 1146 | } else { 1147 | return false; 1148 | } 1149 | } 1150 | return ($checkEmpty && '' === $param) ? false : true; 1151 | } 1152 | 1153 | /** 1154 | * 获取指定的参数 1155 | * @access public 1156 | * @param string|array $name 变量名 1157 | * @param string $type 变量类型 1158 | * @return mixed 1159 | */ 1160 | public function only($name, $type = 'param') 1161 | { 1162 | $param = $this->$type(); 1163 | if (is_string($name)) { 1164 | $name = explode(',', $name); 1165 | } 1166 | $item = []; 1167 | foreach ($name as $key) { 1168 | if (isset($param[$key])) { 1169 | $item[$key] = $param[$key]; 1170 | } 1171 | } 1172 | return $item; 1173 | } 1174 | 1175 | /** 1176 | * 排除指定参数获取 1177 | * @access public 1178 | * @param string|array $name 变量名 1179 | * @param string $type 变量类型 1180 | * @return mixed 1181 | */ 1182 | public function except($name, $type = 'param') 1183 | { 1184 | $param = $this->$type(); 1185 | if (is_string($name)) { 1186 | $name = explode(',', $name); 1187 | } 1188 | foreach ($name as $key) { 1189 | if (isset($param[$key])) { 1190 | unset($param[$key]); 1191 | } 1192 | } 1193 | return $param; 1194 | } 1195 | 1196 | /** 1197 | * 当前是否ssl 1198 | * @access public 1199 | * @return bool 1200 | */ 1201 | public function isSsl() 1202 | { 1203 | $server = array_merge($_SERVER, $this->server); 1204 | if (isset($server['HTTPS']) && ('1' == $server['HTTPS'] || 'on' == strtolower($server['HTTPS']))) { 1205 | return true; 1206 | } elseif (isset($server['REQUEST_SCHEME']) && 'https' == $server['REQUEST_SCHEME']) { 1207 | return true; 1208 | } elseif (isset($server['SERVER_PORT']) && ('443' == $server['SERVER_PORT'])) { 1209 | return true; 1210 | } elseif (isset($server['HTTP_X_FORWARDED_PROTO']) && 'https' == $server['HTTP_X_FORWARDED_PROTO']) { 1211 | return true; 1212 | } elseif (Config::get('https_agent_name') && isset($server[Config::get('https_agent_name')])) { 1213 | return true; 1214 | } 1215 | return false; 1216 | } 1217 | 1218 | /** 1219 | * 当前是否Ajax请求 1220 | * @access public 1221 | * @param bool $ajax true 获取原始ajax请求 1222 | * @return bool 1223 | */ 1224 | public function isAjax($ajax = false) 1225 | { 1226 | $value = $this->server('HTTP_X_REQUESTED_WITH', '', 'strtolower'); 1227 | $result = ('xmlhttprequest' == $value) ? true : false; 1228 | if (true === $ajax) { 1229 | return $result; 1230 | } else { 1231 | return $this->param(Config::get('var_ajax')) ? true : $result; 1232 | } 1233 | } 1234 | 1235 | /** 1236 | * 当前是否Pjax请求 1237 | * @access public 1238 | * @param bool $pjax true 获取原始pjax请求 1239 | * @return bool 1240 | */ 1241 | public function isPjax($pjax = false) 1242 | { 1243 | $result = !is_null($this->server('HTTP_X_PJAX')) ? true : false; 1244 | if (true === $pjax) { 1245 | return $result; 1246 | } else { 1247 | return $this->param(Config::get('var_pjax')) ? true : $result; 1248 | } 1249 | } 1250 | 1251 | /** 1252 | * 获取客户端IP地址 1253 | * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字 1254 | * @param boolean $adv 是否进行高级模式获取(有可能被伪装) 1255 | * @return mixed 1256 | */ 1257 | public function ip($type = 0, $adv = false) 1258 | { 1259 | $type = $type ? 1 : 0; 1260 | static $ip = null; 1261 | if (null !== $ip) { 1262 | return $ip[$type]; 1263 | } 1264 | 1265 | if ($adv) { 1266 | if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { 1267 | $arr = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); 1268 | $pos = array_search('unknown', $arr); 1269 | if (false !== $pos) { 1270 | unset($arr[$pos]); 1271 | } 1272 | $ip = trim(current($arr)); 1273 | } elseif (isset($_SERVER['HTTP_CLIENT_IP'])) { 1274 | $ip = $_SERVER['HTTP_CLIENT_IP']; 1275 | } elseif (isset($_SERVER['REMOTE_ADDR'])) { 1276 | $ip = $_SERVER['REMOTE_ADDR']; 1277 | } 1278 | } elseif (isset($_SERVER['REMOTE_ADDR'])) { 1279 | $ip = $_SERVER['REMOTE_ADDR']; 1280 | } 1281 | // IP地址合法验证 1282 | $long = sprintf("%u", ip2long($ip)); 1283 | $ip = $long ? [$ip, $long] : ['0.0.0.0', 0]; 1284 | return $ip[$type]; 1285 | } 1286 | 1287 | /** 1288 | * 检测是否使用手机访问 1289 | * @access public 1290 | * @return bool 1291 | */ 1292 | public function isMobile() 1293 | { 1294 | if (isset($_SERVER['HTTP_VIA']) && stristr($_SERVER['HTTP_VIA'], "wap")) { 1295 | return true; 1296 | } elseif (isset($_SERVER['HTTP_ACCEPT']) && strpos(strtoupper($_SERVER['HTTP_ACCEPT']), "VND.WAP.WML")) { 1297 | return true; 1298 | } elseif (isset($_SERVER['HTTP_X_WAP_PROFILE']) || isset($_SERVER['HTTP_PROFILE'])) { 1299 | return true; 1300 | } elseif (isset($_SERVER['HTTP_USER_AGENT']) && preg_match('/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i', $_SERVER['HTTP_USER_AGENT'])) { 1301 | return true; 1302 | } else { 1303 | return false; 1304 | } 1305 | } 1306 | 1307 | /** 1308 | * 当前URL地址中的scheme参数 1309 | * @access public 1310 | * @return string 1311 | */ 1312 | public function scheme() 1313 | { 1314 | return $this->isSsl() ? 'https' : 'http'; 1315 | } 1316 | 1317 | /** 1318 | * 当前请求URL地址中的query参数 1319 | * @access public 1320 | * @return string 1321 | */ 1322 | public function query() 1323 | { 1324 | return $this->server('QUERY_STRING'); 1325 | } 1326 | 1327 | /** 1328 | * 当前请求的host 1329 | * @access public 1330 | * @return string 1331 | */ 1332 | public function host() 1333 | { 1334 | return $this->server('HTTP_HOST'); 1335 | } 1336 | 1337 | /** 1338 | * 当前请求URL地址中的port参数 1339 | * @access public 1340 | * @return integer 1341 | */ 1342 | public function port() 1343 | { 1344 | return $this->server('SERVER_PORT'); 1345 | } 1346 | 1347 | /** 1348 | * 当前请求 SERVER_PROTOCOL 1349 | * @access public 1350 | * @return integer 1351 | */ 1352 | public function protocol() 1353 | { 1354 | return $this->server('SERVER_PROTOCOL'); 1355 | } 1356 | 1357 | /** 1358 | * 当前请求 REMOTE_PORT 1359 | * @access public 1360 | * @return integer 1361 | */ 1362 | public function remotePort() 1363 | { 1364 | return $this->server('REMOTE_PORT'); 1365 | } 1366 | 1367 | /** 1368 | * 当前请求 HTTP_CONTENT_TYPE 1369 | * @access public 1370 | * @return string 1371 | */ 1372 | public function contentType() 1373 | { 1374 | $contentType = $this->server('CONTENT_TYPE'); 1375 | if ($contentType) { 1376 | if (strpos($contentType, ';')) { 1377 | list($type) = explode(';', $contentType); 1378 | } else { 1379 | $type = $contentType; 1380 | } 1381 | return trim($type); 1382 | } 1383 | return ''; 1384 | } 1385 | 1386 | /** 1387 | * 获取当前请求的路由信息 1388 | * @access public 1389 | * @param array $route 路由名称 1390 | * @return array 1391 | */ 1392 | public function routeInfo($route = []) 1393 | { 1394 | if (!empty($route)) { 1395 | $this->routeInfo = $route; 1396 | } else { 1397 | return $this->routeInfo; 1398 | } 1399 | } 1400 | 1401 | /** 1402 | * 设置或者获取当前请求的调度信息 1403 | * @access public 1404 | * @param array $dispatch 调度信息 1405 | * @return array 1406 | */ 1407 | public function dispatch($dispatch = null) 1408 | { 1409 | if (!is_null($dispatch)) { 1410 | $this->dispatch = $dispatch; 1411 | } 1412 | return $this->dispatch; 1413 | } 1414 | 1415 | /** 1416 | * 设置或者获取当前的模块名 1417 | * @access public 1418 | * @param string $module 模块名 1419 | * @return string|Request 1420 | */ 1421 | public function module($module = null) 1422 | { 1423 | if (!is_null($module)) { 1424 | $this->module = $module; 1425 | return $this; 1426 | } else { 1427 | return $this->module ?: ''; 1428 | } 1429 | } 1430 | 1431 | /** 1432 | * 设置或者获取当前的控制器名 1433 | * @access public 1434 | * @param string $controller 控制器名 1435 | * @return string|Request 1436 | */ 1437 | public function controller($controller = null) 1438 | { 1439 | if (!is_null($controller)) { 1440 | $this->controller = $controller; 1441 | return $this; 1442 | } else { 1443 | return $this->controller ?: ''; 1444 | } 1445 | } 1446 | 1447 | /** 1448 | * 设置或者获取当前的操作名 1449 | * @access public 1450 | * @param string $action 操作名 1451 | * @return string|Request 1452 | */ 1453 | public function action($action = null) 1454 | { 1455 | if (!is_null($action)) { 1456 | $this->action = $action; 1457 | return $this; 1458 | } else { 1459 | return $this->action ?: ''; 1460 | } 1461 | } 1462 | 1463 | /** 1464 | * 设置或者获取当前的语言 1465 | * @access public 1466 | * @param string $lang 语言名 1467 | * @return string|Request 1468 | */ 1469 | public function langset($lang = null) 1470 | { 1471 | if (!is_null($lang)) { 1472 | $this->langset = $lang; 1473 | return $this; 1474 | } else { 1475 | return $this->langset ?: ''; 1476 | } 1477 | } 1478 | 1479 | /** 1480 | * 设置或者获取当前请求的content 1481 | * @access public 1482 | * @return string 1483 | */ 1484 | public function getContent() 1485 | { 1486 | if (is_null($this->content)) { 1487 | $this->content = $this->input; 1488 | } 1489 | return $this->content; 1490 | } 1491 | 1492 | /** 1493 | * 获取当前请求的php://input 1494 | * @access public 1495 | * @return string 1496 | */ 1497 | public function getInput() 1498 | { 1499 | return $this->input; 1500 | } 1501 | 1502 | /** 1503 | * 生成请求令牌 1504 | * @access public 1505 | * @param string $name 令牌名称 1506 | * @param mixed $type 令牌生成方法 1507 | * @return string 1508 | */ 1509 | public function token($name = '__token__', $type = 'md5') 1510 | { 1511 | $type = is_callable($type) ? $type : 'md5'; 1512 | $token = call_user_func($type, $_SERVER['REQUEST_TIME_FLOAT']); 1513 | if ($this->isAjax()) { 1514 | header($name . ': ' . $token); 1515 | } 1516 | Session::set($name, $token); 1517 | return $token; 1518 | } 1519 | 1520 | /** 1521 | * 设置当前地址的请求缓存 1522 | * @access public 1523 | * @param string $key 缓存标识,支持变量规则 ,例如 item/:name/:id 1524 | * @param mixed $expire 缓存有效期 1525 | * @param array $except 缓存排除 1526 | * @param string $tag 缓存标签 1527 | * @return void 1528 | */ 1529 | public function cache($key, $expire = null, $except = [], $tag = null) 1530 | { 1531 | if (!is_array($except)) { 1532 | $tag = $except; 1533 | $except = []; 1534 | } 1535 | 1536 | if (false !== $key && $this->isGet() && !$this->isCheckCache) { 1537 | // 标记请求缓存检查 1538 | $this->isCheckCache = true; 1539 | if (false === $expire) { 1540 | // 关闭当前缓存 1541 | return; 1542 | } 1543 | if ($key instanceof \Closure) { 1544 | $key = call_user_func_array($key, [$this]); 1545 | } elseif (true === $key) { 1546 | foreach ($except as $rule) { 1547 | if (0 === stripos($this->url(), $rule)) { 1548 | return; 1549 | } 1550 | } 1551 | // 自动缓存功能 1552 | $key = '__URL__'; 1553 | } elseif (strpos($key, '|')) { 1554 | list($key, $fun) = explode('|', $key); 1555 | } 1556 | // 特殊规则替换 1557 | if (false !== strpos($key, '__')) { 1558 | $key = str_replace(['__MODULE__', '__CONTROLLER__', '__ACTION__', '__URL__', ''], [$this->module, $this->controller, $this->action, md5($this->url(true))], $key); 1559 | } 1560 | 1561 | if (false !== strpos($key, ':')) { 1562 | $param = $this->param(); 1563 | foreach ($param as $item => $val) { 1564 | if (is_string($val) && false !== strpos($key, ':' . $item)) { 1565 | $key = str_replace(':' . $item, $val, $key); 1566 | } 1567 | } 1568 | } elseif (strpos($key, ']')) { 1569 | if ('[' . $this->ext() . ']' == $key) { 1570 | // 缓存某个后缀的请求 1571 | $key = md5($this->url()); 1572 | } else { 1573 | return; 1574 | } 1575 | } 1576 | if (isset($fun)) { 1577 | $key = $fun($key); 1578 | } 1579 | 1580 | if (strtotime($this->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $_SERVER['REQUEST_TIME']) { 1581 | // 读取缓存 1582 | $response = Response::create()->code(304); 1583 | throw new \Andromeda\Exception($response); 1584 | } elseif (Cache::has($key)) { 1585 | list($content, $header) = Cache::get($key); 1586 | $response = Response::create($content)->header($header); 1587 | throw new \Andromeda\Exception($response); 1588 | } else { 1589 | $this->cache = [$key, $expire, $tag]; 1590 | } 1591 | } 1592 | } 1593 | 1594 | /** 1595 | * 读取请求缓存设置 1596 | * @access public 1597 | * @return array 1598 | */ 1599 | public function getCache() 1600 | { 1601 | return $this->cache; 1602 | } 1603 | 1604 | /** 1605 | * 设置当前请求绑定的对象实例 1606 | * @access public 1607 | * @param string|array $name 绑定的对象标识 1608 | * @param mixed $obj 绑定的对象实例 1609 | * @return mixed 1610 | */ 1611 | public function bind($name, $obj = null) 1612 | { 1613 | if (is_array($name)) { 1614 | $this->bind = array_merge($this->bind, $name); 1615 | } else { 1616 | $this->bind[$name] = $obj; 1617 | } 1618 | } 1619 | 1620 | public function __set($name, $value) 1621 | { 1622 | $this->bind[$name] = $value; 1623 | } 1624 | 1625 | public function __get($name) 1626 | { 1627 | return isset($this->bind[$name]) ? $this->bind[$name] : null; 1628 | } 1629 | 1630 | public function __isset($name) 1631 | { 1632 | return isset($this->bind[$name]); 1633 | } 1634 | } 1635 | -------------------------------------------------------------------------------- /Andromeda/Response.php: -------------------------------------------------------------------------------- 1 | 10 | // +---------------------------------------------------------------------- 11 | 12 | namespace Andromeda; 13 | 14 | 15 | class Response 16 | { 17 | // 原始数据 18 | protected $data; 19 | 20 | // 当前的contentType 21 | protected $contentType = 'text/html'; 22 | 23 | // 字符集 24 | protected $charset = 'utf-8'; 25 | 26 | //状态 27 | protected $code = 200; 28 | 29 | // 输出参数 30 | protected $options = []; 31 | // header参数 32 | protected $header = []; 33 | 34 | protected $content = null; 35 | 36 | /** 37 | * 构造函数 38 | * @access public 39 | * @param mixed $data 输出数据 40 | * @param int $code 41 | * @param array $header 42 | * @param array $options 输出参数 43 | */ 44 | public function __construct($data = '', $code = 200, array $header = [], $options = []) 45 | { 46 | $this->data($data); 47 | if (!empty($options)) { 48 | $this->options = array_merge($this->options, $options); 49 | } 50 | $this->contentType($this->contentType, $this->charset); 51 | $this->header = array_merge($this->header, $header); 52 | $this->code = $code; 53 | } 54 | 55 | /** 56 | * 创建Response对象 57 | * @access public 58 | * @param mixed $data 输出数据 59 | * @param string $type 输出类型 60 | * @param int $code 61 | * @param array $header 62 | * @param array $options 输出参数 63 | * @return Response 64 | */ 65 | public static function create($data = '', $type = '', $code = 200, array $header = [], $options = []) 66 | { 67 | $type = empty($type) ? 'null' : strtolower($type); 68 | 69 | $class = false !== strpos($type, '\\') ? $type : '\\think\\response\\' . ucfirst($type); 70 | if (class_exists($class)) { 71 | $response = new $class($data, $code, $header, $options); 72 | } else { 73 | $response = new static($data, $code, $header, $options); 74 | } 75 | 76 | return $response; 77 | } 78 | 79 | /** 80 | * 发送数据到客户端 81 | * @access public 82 | * @return mixed 83 | * @throws \InvalidArgumentException 84 | */ 85 | public function send() 86 | { 87 | // 监听response_send 88 | Hook::listen('response_send', $this); 89 | 90 | // 处理输出数据 91 | $data = $this->getContent(); 92 | 93 | // Trace调试注入 94 | if (Env::get('app_trace', Config::get('app_trace'))) { 95 | Debug::inject($this, $data); 96 | } 97 | 98 | if (200 == $this->code) { 99 | $cache = Request::instance()->getCache(); 100 | if ($cache) { 101 | $this->header['Cache-Control'] = 'max-age=' . $cache[1] . ',must-revalidate'; 102 | $this->header['Last-Modified'] = gmdate('D, d M Y H:i:s') . ' GMT'; 103 | $this->header['Expires'] = gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT'; 104 | Cache::tag($cache[2])->set($cache[0], [$data, $this->header], $cache[1]); 105 | } 106 | } 107 | 108 | if (!headers_sent() && !empty($this->header)) { 109 | // 发送状态码 110 | http_response_code($this->code); 111 | // 发送头部信息 112 | foreach ($this->header as $name => $val) { 113 | if (is_null($val)) { 114 | header($name); 115 | } else { 116 | header($name . ':' . $val); 117 | } 118 | } 119 | } 120 | 121 | echo $data; 122 | 123 | if (function_exists('fastcgi_finish_request')) { 124 | // 提高页面响应 125 | fastcgi_finish_request(); 126 | } 127 | 128 | // 监听response_end 129 | Hook::listen('response_end', $this); 130 | 131 | // 清空当次请求有效的数据 132 | if (!($this instanceof RedirectResponse)) { 133 | Session::flush(); 134 | } 135 | } 136 | 137 | /** 138 | * 处理数据 139 | * @access protected 140 | * @param mixed $data 要处理的数据 141 | * @return mixed 142 | */ 143 | protected function output($data) 144 | { 145 | return $data; 146 | } 147 | 148 | /** 149 | * 输出的参数 150 | * @access public 151 | * @param mixed $options 输出参数 152 | * @return $this 153 | */ 154 | public function options($options = []) 155 | { 156 | $this->options = array_merge($this->options, $options); 157 | return $this; 158 | } 159 | 160 | /** 161 | * 输出数据设置 162 | * @access public 163 | * @param mixed $data 输出数据 164 | * @return $this 165 | */ 166 | public function data($data) 167 | { 168 | $this->data = $data; 169 | return $this; 170 | } 171 | 172 | /** 173 | * 设置响应头 174 | * @access public 175 | * @param string|array $name 参数名 176 | * @param string $value 参数值 177 | * @return $this 178 | */ 179 | public function header($name, $value = null) 180 | { 181 | if (is_array($name)) { 182 | $this->header = array_merge($this->header, $name); 183 | } else { 184 | $this->header[$name] = $value; 185 | } 186 | return $this; 187 | } 188 | 189 | /** 190 | * 设置页面输出内容 191 | * @param $content 192 | * @return $this 193 | */ 194 | public function content($content) 195 | { 196 | if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([ 197 | $content, 198 | '__toString', 199 | ]) 200 | ) { 201 | throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content))); 202 | } 203 | 204 | $this->content = (string) $content; 205 | 206 | return $this; 207 | } 208 | 209 | /** 210 | * 发送HTTP状态 211 | * @param integer $code 状态码 212 | * @return $this 213 | */ 214 | public function code($code) 215 | { 216 | $this->code = $code; 217 | return $this; 218 | } 219 | 220 | /** 221 | * LastModified 222 | * @param string $time 223 | * @return $this 224 | */ 225 | public function lastModified($time) 226 | { 227 | $this->header['Last-Modified'] = $time; 228 | return $this; 229 | } 230 | 231 | /** 232 | * Expires 233 | * @param string $time 234 | * @return $this 235 | */ 236 | public function expires($time) 237 | { 238 | $this->header['Expires'] = $time; 239 | return $this; 240 | } 241 | 242 | /** 243 | * ETag 244 | * @param string $eTag 245 | * @return $this 246 | */ 247 | public function eTag($eTag) 248 | { 249 | $this->header['ETag'] = $eTag; 250 | return $this; 251 | } 252 | 253 | /** 254 | * 页面缓存控制 255 | * @param string $cache 状态码 256 | * @return $this 257 | */ 258 | public function cacheControl($cache) 259 | { 260 | $this->header['Cache-control'] = $cache; 261 | return $this; 262 | } 263 | 264 | /** 265 | * 页面输出类型 266 | * @param string $contentType 输出类型 267 | * @param string $charset 输出编码 268 | * @return $this 269 | */ 270 | public function contentType($contentType, $charset = 'utf-8') 271 | { 272 | $this->header['Content-Type'] = $contentType . '; charset=' . $charset; 273 | return $this; 274 | } 275 | 276 | /** 277 | * 获取头部信息 278 | * @param string $name 头部名称 279 | * @return mixed 280 | */ 281 | public function getHeader($name = '') 282 | { 283 | if (!empty($name)) { 284 | return isset($this->header[$name]) ? $this->header[$name] : null; 285 | } else { 286 | return $this->header; 287 | } 288 | } 289 | 290 | /** 291 | * 获取原始数据 292 | * @return mixed 293 | */ 294 | public function getData() 295 | { 296 | return $this->data; 297 | } 298 | 299 | /** 300 | * 获取输出数据 301 | * @return mixed 302 | */ 303 | public function getContent() 304 | { 305 | if (null == $this->content) { 306 | $content = $this->output($this->data); 307 | 308 | if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable([ 309 | $content, 310 | '__toString', 311 | ]) 312 | ) { 313 | throw new \InvalidArgumentException(sprintf('variable type error: %s', gettype($content))); 314 | } 315 | 316 | $this->content = (string) $content; 317 | } 318 | return $this->content; 319 | } 320 | 321 | /** 322 | * 获取状态码 323 | * @return integer 324 | */ 325 | public function getCode() 326 | { 327 | return $this->code; 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /Andromeda/core/Controller.class.php: -------------------------------------------------------------------------------- 1 | loader=new Loader(); 10 | $this->view=new View(); 11 | $this->di=$di; 12 | 13 | 14 | } 15 | public function redirect($url,$message,$wait=0){ 16 | if($wait=0){ 17 | header("Location:$url"); 18 | 19 | }else{ 20 | include CURR_VIEW_PATH."message.html"; 21 | 22 | } 23 | exit; 24 | 25 | } 26 | 27 | protected function assign($name,$value='') { 28 | $this->view->assign($name,$value); 29 | return $this; 30 | } 31 | 32 | protected function display($template){ 33 | $this->view->display(CURR_VIEW_PATH.$template); 34 | 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Andromeda/core/Loader.class.php: -------------------------------------------------------------------------------- 1 | db = Mysql::getInstance($dbConfig); 23 | 24 | $this->table = $GLOBALS['config']['DB_PREFIX'] . $table; 25 | $this->getFields(); 26 | 27 | } 28 | 29 | //get the list of fields 30 | private function getFields() 31 | { 32 | $sql = "DESC " . $this->table; 33 | $result = $this->db->query($sql); 34 | foreach ($result as $v) { 35 | $this->fields[] = $v['Field']; 36 | if ($v['Key'] == 'PRI') { 37 | //if there is ok, save it in $pk 38 | $pk = $v['Field']; 39 | 40 | } 41 | } 42 | 43 | //if there is PK, add it into fields list 44 | if (isset($pk)) { 45 | $this->fields['pk'] = $pk; 46 | 47 | } 48 | } 49 | 50 | /** 51 | * Insert records 52 | * @access public 53 | * @param $list array associative array 54 | * @return mixed If succeed return inserted record id, else return false 55 | */ 56 | public function insert($list) 57 | { 58 | $field_list = '';//field list string 59 | $value_list = '';//value list string 60 | foreach ($list as $k => $v) { 61 | if (in_array($k, $this->fields)) { 62 | $field_list .= "`" . $k . "`" . ','; 63 | $value_list .= "'" . $v . "'" . ','; 64 | } 65 | } 66 | 67 | //trim the comma on the right 68 | $field_list = rtrim($field_list, ','); 69 | $value_list = rtrim($value_list, ','); 70 | //Construct sql statement 71 | $sql = "insert into '{$this->table}' ({$field_list}) values ($value_list)"; 72 | if ($this->db->query($sql)) { 73 | //insert succeed,return the last record's id; 74 | return $this->db->getInsertId(); 75 | 76 | } else { 77 | return false; 78 | 79 | } 80 | } 81 | 82 | /* 83 | update records 84 | @access public 85 | @param $list array associative array needs to be updated 86 | @return mixed if succeed return the count of affected rows,else return false 87 | */ 88 | public function update($list) 89 | { 90 | $upList = '';//update fields 91 | $where = 0;//update condition,default is 0; 92 | $update = ''; 93 | foreach ($list as $k => $v) { 94 | if (in_array($k, $this->fields)) { 95 | if ($k == $this->fields['pk']) { 96 | //if it's PK,construct where condition 97 | $where = "'$k'=$v"; 98 | 99 | } else { 100 | //if not PK,construct update list 101 | $update = $update . "'$k'=$v" . ","; 102 | 103 | } 104 | } 105 | } 106 | //trim comma on the right of update list 107 | 108 | //construct SQL statement 109 | 110 | $sql = "update '{$this->table}' set {$upList} where {$where}"; 111 | if ($this->db->query($sql)) { 112 | //if succeed,return the count of affected rows 113 | 114 | if ($rows = mysql_affected_rows()) { 115 | //has count of affected rows 116 | return $rows; 117 | 118 | } else { 119 | 120 | //failed 121 | return false; 122 | 123 | } 124 | 125 | } else { 126 | return false; 127 | 128 | } 129 | } 130 | 131 | /* 132 | delete records 133 | @access public 134 | @param $pk mixed could be an int or a array 135 | @return mixed if succeed,return the count of deleted rows ,if fail ,return false 136 | 137 | */ 138 | public function delete($pk) 139 | { 140 | $where = 0;//condition string 141 | //check if $pk is a single value or array,and construct where condition accordingly 142 | 143 | if (is_array($pk)) { 144 | //is array 145 | $where = "'{$this->fields['pk']}' in (" . implode(',', $pk) . ")"; 146 | 147 | } else { 148 | //single value 149 | $where = "'{$this->fields['pk']}'=$pk"; 150 | 151 | } 152 | 153 | //construct SQL statement 154 | $sql = "DELETE FROM '{$this->table}' WHERE $where"; 155 | if ($this->db->query($sql)) { 156 | //if succeed return the count of affected rows; 157 | if ($rows = mysql_affected_rows()) { 158 | //has count of affected rows 159 | return $rows; 160 | } else { 161 | return false; 162 | 163 | } 164 | 165 | } else { 166 | return false; 167 | 168 | } 169 | } 170 | 171 | /** * Get info based on PK 172 | * @param $pk int Primary Key 173 | * @return array an array of single record 174 | */ 175 | 176 | public function selectByPk($pk) 177 | { 178 | $sql = "select * from '{$this->table}' where '{$this->fields['pk']}'=$pk"; 179 | return $this->db->getRow($sql); 180 | 181 | } 182 | 183 | /* 184 | get the count of all records 185 | */ 186 | public function total() 187 | { 188 | $sql = "select count(*) from {$this->table}"; 189 | return $this->db->getOne($sql); 190 | 191 | } 192 | 193 | /* 194 | get info of pagination 195 | @param $offset int offset value 196 | @param $limit int number of records of each fetch 197 | @param $where string where condition,default is empty 198 | */ 199 | public function pageRows($offset, $limit, $where = '') 200 | { 201 | if (empty($where)) { 202 | $sql = "select * from {$this->table} limit $offset,$limit"; 203 | } else { 204 | $sql = "select * from {$this->table} where $where limit $offset,$limit"; 205 | } 206 | return $this->db->getAll($sql); 207 | 208 | } 209 | 210 | 211 | } 212 | 213 | -------------------------------------------------------------------------------- /Andromeda/core/Mysql.class.php: -------------------------------------------------------------------------------- 1 | 6 | * @blog http://www.descartes.top/ 7 | * @version >5.1 utf8 8 | */ 9 | class Mysql 10 | { 11 | protected static $_instance = null; 12 | protected $dbName = ''; 13 | protected $dsn; 14 | protected $dbClient; 15 | 16 | /** 17 | * 构造 18 | * 19 | * @param array $config 20 | * @throws Exception 21 | */ 22 | private function __construct(array $config) 23 | { 24 | $host = isset($config['host']) ? $config['host'] : 'localhost'; 25 | 26 | $user = isset($config['user']) ? $config['user'] : 'root'; 27 | 28 | $password = isset($config['password']) ? $config['password'] : ''; 29 | 30 | $db_name = isset($config['db_name']) ? $config['db_name'] : ''; 31 | 32 | $port = isset($config['port']) ? $config['port'] : '3306'; 33 | 34 | $charset = isset($config['charset']) ? $config['charset'] : 'utf-8'; 35 | 36 | try { 37 | $this->dsn = 'mysql:host=' . $host . ';dbname=' . $db_name.";port=".$port; 38 | $this->dbClient = new PDO($this->dsn, $user, $password); 39 | $this->dbClient->exec('SET character_set_connection=' . $charset . ', character_set_results=' . $charset . ', character_set_client=binary'); 40 | } catch (PDOException $e) { 41 | $this->outputError($e->getMessage()); 42 | } 43 | } 44 | 45 | /** 46 | * 防止克隆 47 | * 48 | */ 49 | private function __clone() 50 | { 51 | } 52 | 53 | /** 54 | * Singleton instance 55 | * 56 | * @param array $config 57 | * @return Object 58 | * @throws Exception 59 | */ 60 | public static function getInstance(array $config) 61 | { 62 | if (self::$_instance === null) { 63 | self::$_instance = new self($config); 64 | } 65 | return self::$_instance; 66 | } 67 | 68 | /** 69 | * Query 查询 70 | * 71 | * @param String $strSql SQL语句 72 | * @param String $queryMode 查询方式(All or Row) 73 | * @param Boolean $debug 74 | * @return array 75 | */ 76 | public function query($strSql, $queryMode = 'All', $debug = false) 77 | { 78 | if ($debug === true) $this->debug($strSql); 79 | $recordset = $this->dbClient->query($strSql); 80 | $this->getPDOError(); 81 | if ($recordset) { 82 | $recordset->setFetchMode(PDO::FETCH_ASSOC); 83 | if ($queryMode == 'All') { 84 | $result = $recordset->fetchAll(); 85 | } elseif ($queryMode == 'Row') { 86 | $result = $recordset->fetch(); 87 | } 88 | } else { 89 | $result = null; 90 | } 91 | return $result; 92 | } 93 | 94 | /** 95 | * Update 更新 96 | * 97 | * @param String $table 表名 98 | * @param array $arrayDataValue 字段与值 99 | * @param String $where 条件 100 | * @param Boolean $debug 101 | * @return Int 102 | */ 103 | public function update($table, $arrayDataValue, $where = '', $debug = false) 104 | { 105 | $this->checkFields($table, $arrayDataValue); 106 | if ($where) { 107 | $strSql = ''; 108 | foreach ($arrayDataValue as $key => $value) { 109 | $strSql .= ", `$key`='$value'"; 110 | } 111 | $strSql = substr($strSql, 1); 112 | $strSql = "UPDATE `$table` SET $strSql WHERE $where"; 113 | } else { 114 | $strSql = "REPLACE INTO `$table` (`" . implode('`,`', array_keys($arrayDataValue)) . "`) VALUES ('" . implode("','", $arrayDataValue) . "')"; 115 | } 116 | if ($debug === true) $this->debug($strSql); 117 | $result = $this->dbClient->exec($strSql); 118 | $this->getPDOError(); 119 | return $result; 120 | } 121 | 122 | /** 123 | * Insert 插入 124 | * 125 | * @param String $table 表名 126 | * @param Array $arrayDataValue 字段与值 127 | * @param Boolean $debug 128 | * @return Int 129 | */ 130 | public function insert($table, $arrayDataValue, $debug = false) 131 | { 132 | $this->checkFields($table, $arrayDataValue); 133 | $strSql = "INSERT INTO `$table` (`" . implode('`,`', array_keys($arrayDataValue)) . "`) VALUES ('" . implode("','", $arrayDataValue) . "')"; 134 | if ($debug === true) $this->debug($strSql); 135 | $result = $this->dbClient->exec($strSql); 136 | $this->getPDOError(); 137 | return $result; 138 | } 139 | 140 | /** 141 | * Replace 覆盖方式插入 142 | * 143 | * @param String $table 表名 144 | * @param Array $arrayDataValue 字段与值 145 | * @param Boolean $debug 146 | * @return Int 147 | */ 148 | public function replace($table, $arrayDataValue, $debug = false) 149 | { 150 | $this->checkFields($table, $arrayDataValue); 151 | $strSql = "REPLACE INTO `$table`(`" . implode('`,`', array_keys($arrayDataValue)) . "`) VALUES ('" . implode("','", $arrayDataValue) . "')"; 152 | if ($debug === true) $this->debug($strSql); 153 | $result = $this->dbClient->exec($strSql); 154 | $this->getPDOError(); 155 | return $result; 156 | } 157 | 158 | /** 159 | * Delete 删除 160 | * 161 | * @param String $table 表名 162 | * @param String $where 条件 163 | * @param Boolean $debug 164 | * @return Int 165 | */ 166 | public function delete($table, $where = '', $debug = false) 167 | { 168 | if ($where == '') { 169 | $this->outputError("'WHERE' is Null"); 170 | } else { 171 | $strSql = "DELETE FROM `$table` WHERE $where"; 172 | if ($debug === true) $this->debug($strSql); 173 | $result = $this->dbClient->exec($strSql); 174 | $this->getPDOError(); 175 | return $result; 176 | } 177 | } 178 | 179 | /** 180 | * execSql 执行SQL语句,debug=>true可打印sql调试 181 | * 182 | * @param String $strSql 183 | * @param Boolean $debug 184 | * @return Int 185 | */ 186 | public function execSql($strSql, $debug = false) 187 | { 188 | if ($debug === true) $this->debug($strSql); 189 | $result = $this->dbClient->exec($strSql); 190 | $this->getPDOError(); 191 | return $result; 192 | } 193 | 194 | /** 195 | * 获取字段最大值 196 | * 197 | * @param string $table 表名 198 | * @param string $field_name 字段名 199 | * @param string $where 条件 200 | */ 201 | public function getMaxValue($table, $field_name, $where = '', $debug = false) 202 | { 203 | $strSql = "SELECT MAX(" . $field_name . ") AS MAX_VALUE FROM $table"; 204 | if ($where != '') $strSql .= " WHERE $where"; 205 | if ($debug === true) $this->debug($strSql); 206 | $arrTemp = $this->query($strSql, 'Row'); 207 | $maxValue = $arrTemp["MAX_VALUE"]; 208 | if ($maxValue == "" || $maxValue == null) { 209 | $maxValue = 0; 210 | } 211 | return $maxValue; 212 | } 213 | 214 | /** 215 | * 获取指定列的数量 216 | * 217 | * @param string $table 218 | * @param string $field_name 219 | * @param string $where 220 | * @param bool $debug 221 | * @return int 222 | */ 223 | public function getCount($table, $field_name, $where = '', $debug = false) 224 | { 225 | $strSql = "SELECT COUNT($field_name) AS NUM FROM $table"; 226 | if ($where != '') $strSql .= " WHERE $where"; 227 | if ($debug === true) $this->debug($strSql); 228 | $arrTemp = $this->query($strSql, 'Row'); 229 | return $arrTemp['NUM']; 230 | } 231 | 232 | /** 233 | * 获取表引擎 234 | * 235 | * @param String $dbName 库名 236 | * @param String $tableName 表名 237 | * @param Boolean $debug 238 | * @return String 239 | */ 240 | public function getTableEngine($dbName, $tableName) 241 | { 242 | $strSql = "SHOW TABLE STATUS FROM $dbName WHERE Name='" . $tableName . "'"; 243 | $arrayTableInfo = $this->query($strSql); 244 | $this->getPDOError(); 245 | return $arrayTableInfo[0]['Engine']; 246 | } 247 | 248 | //预处理执行 249 | public function prepareSql($sql = '') 250 | { 251 | return $this->dbClient->prepare($sql); 252 | } 253 | 254 | //执行预处理 255 | public function execute($presql) 256 | { 257 | return $this->dbClient->execute($presql); 258 | } 259 | 260 | /** 261 | * pdo属性设置 262 | */ 263 | public function setAttribute($p, $d) 264 | { 265 | $this->dbClient->setAttribute($p, $d); 266 | } 267 | 268 | /** 269 | * beginTransaction 事务开始 270 | */ 271 | public function beginTransaction() 272 | { 273 | $this->dbClient->beginTransaction(); 274 | } 275 | 276 | /** 277 | * commit 事务提交 278 | */ 279 | public function commit() 280 | { 281 | $this->dbClient->commit(); 282 | } 283 | 284 | /** 285 | * rollback 事务回滚 286 | */ 287 | public function rollback() 288 | { 289 | $this->dbClient->rollback(); 290 | } 291 | 292 | /** 293 | * transaction 通过事务处理多条SQL语句 294 | * 调用前需通过getTableEngine判断表引擎是否支持事务 295 | * 296 | * @param array $arraySql 297 | * @return Boolean 298 | */ 299 | public function execTransaction($arraySql) 300 | { 301 | $retval = 1; 302 | $this->beginTransaction(); 303 | foreach ($arraySql as $strSql) { 304 | if ($this->execSql($strSql) == 0) $retval = 0; 305 | } 306 | if ($retval == 0) { 307 | $this->rollback(); 308 | return false; 309 | } else { 310 | $this->commit(); 311 | return true; 312 | } 313 | } 314 | 315 | /** 316 | * checkFields 检查指定字段是否在指定数据表中存在 317 | * 318 | * @param String $table 319 | * @param array $arrayField 320 | */ 321 | private function checkFields($table, $arrayFields) 322 | { 323 | $fields = $this->getFields($table); 324 | foreach ($arrayFields as $key => $value) { 325 | if (!in_array($key, $fields)) { 326 | $this->outputError("Unknown column `$key` in field list."); 327 | } 328 | } 329 | } 330 | 331 | /** 332 | * getFields 获取指定数据表中的全部字段名 333 | * 334 | * @param String $table 表名 335 | * @return array 336 | */ 337 | private function getFields($table) 338 | { 339 | $fields = array(); 340 | $recordset = $this->dbClient->query("SHOW COLUMNS FROM $table"); 341 | $this->getPDOError(); 342 | $recordset->setFetchMode(PDO::FETCH_ASSOC); 343 | $result = $recordset->fetchAll(); 344 | foreach ($result as $rows) { 345 | $fields[] = $rows['Field']; 346 | } 347 | return $fields; 348 | } 349 | 350 | /** 351 | * getPDOError 捕获PDO错误信息 352 | */ 353 | private function getPDOError() 354 | { 355 | if ($this->dbClient->errorCode() != '00000') { 356 | $arrayError = $this->dbClient->errorInfo(); 357 | $this->outputError($arrayError[2]); 358 | } 359 | } 360 | 361 | /** 362 | * debug 363 | * 364 | * @param mixed $debuginfo 365 | */ 366 | private function debug($debuginfo) 367 | { 368 | var_dump($debuginfo); 369 | exit(); 370 | } 371 | 372 | /** 373 | * 输出错误信息 374 | * 375 | * @param String $strErrMsg 376 | * @throws Exception 377 | */ 378 | private function outputError($strErrMsg) 379 | { 380 | throw new Exception('MySQL Error: ' . $strErrMsg); 381 | } 382 | 383 | /** 384 | * destruct 关闭数据库连接 385 | */ 386 | public function destruct() 387 | { 388 | $this->dbClient = null; 389 | } 390 | 391 | /** 392 | *PDO执行sql语句,返回改变的条数 393 | *如需调试可选用execSql($sql,true) 394 | */ 395 | public function exec($sql = '') 396 | { 397 | return $this->dbClient->exec($sql); 398 | } 399 | } 400 | 401 | 402 | -------------------------------------------------------------------------------- /Andromeda/core/TemplateEngine/Compile.class.php: -------------------------------------------------------------------------------- 1 | template = $template; 21 | $this->comfile = $compileFile; 22 | $this->content = file_get_contents($template); 23 | if($config['php_turn'] === false) 24 | { 25 | $this->T_P[] = "/<\?(=|php|)(.+?)\?>/is"; 26 | $this->T_R[] = "<? \\1\\2? >"; 27 | } 28 | 29 | //{$var} 30 | $this->T_P[] = "/\{\\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/"; 31 | 32 | //{foreach $b}或者{loop $b} 33 | $this->T_P[] = "/\{(loop|foreach) \\$([a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)\}/i"; 34 | 35 | //{[K|V]} 36 | $this->T_P[] = "/\{([K|V])\}/"; 37 | 38 | //{/foreach}或者{\loop}或者{\if} 39 | $this->T_P[] = "/\{\/(loop|foreach|if)}/i"; 40 | 41 | //{if (condition)} 42 | $this->T_P[] = "/\{if (.* ?)\}/i"; 43 | 44 | //{(else if | elseif)} 45 | $this->T_P[] = "/\{(else if|elseif) (.* ?)\}/i"; 46 | 47 | //{else} 48 | $this->T_P[] = "/\{else\}/i"; 49 | 50 | //{#...# 或者 *...#,注释} 51 | $this->T_P[] = "/\{(\#|\*)(.* ?)(\#|\*)\}/"; 52 | 53 | $this->T_R[] = "value['\\1']; ?>"; 54 | $this->T_R[] = "value['\\2'] as \$K => \$V) { ?>"; 55 | $this->T_R[] = ""; 56 | $this->T_R[] = ""; 57 | $this->T_R[] = ""; 58 | $this->T_R[] = ""; 59 | $this->T_R[] = ""; 60 | $this->T_R[] = ""; 61 | } 62 | 63 | public function compile() 64 | { 65 | $this->c_all(); 66 | $this->c_staticFile(); 67 | file_put_contents($this->comfile, $this->content); 68 | } 69 | 70 | public function c_all() 71 | { 72 | $this->content = preg_replace($this->T_P, $this->T_R, $this->content); 73 | } 74 | 75 | /** 76 | * 加入对JavaScript文件的解析 77 | * @return [type] [description] 78 | */ 79 | public function c_staticFile() 80 | { 81 | $this->content = preg_replace('/\{\!(.* ?)\!\}/', '', $this->content); 82 | } 83 | 84 | public function __set($name, $value) 85 | { 86 | $this->$name = $value; 87 | } 88 | 89 | public function __get($name) 90 | { 91 | if(isset($this->$name)) 92 | { 93 | return $this->$name; 94 | } 95 | else 96 | { 97 | return null; 98 | } 99 | } 100 | } -------------------------------------------------------------------------------- /Andromeda/core/TemplateEngine/Template.class.php: -------------------------------------------------------------------------------- 1 | '.tpl', //模板的后缀 11 | 'templateDir' => "template/", //模板所在的文件夹 12 | 'compileDir' => "cache/", //编译后存放的目录 13 | 'cache_html' => false, //是否需要编译成静态的html文件 14 | 'suffix_cache' => '.html', //设置编译文件的后缀 15 | 'cache_time' => 7200, //设置多长时间自动更新 16 | 'php_turn' => true, //设置是否支持php原生代码 17 | 'debug' => false, 18 | ); 19 | 20 | public $file; //模板文件名,不带路径 21 | public $debug = array(); //调试信息 22 | private $value = array(); //值栈 23 | private $compileTool; //编译器 24 | private $controlData = array(); 25 | static private $instance = null; //模板类对象 26 | 27 | public function __construct($arrayConfig = array()) 28 | { 29 | $this->debug['begin'] = microtime(true); 30 | $this->arrayConfig = array_merge($this->arrayConfig, $arrayConfig); 31 | //$this->getPath(); 32 | 33 | 34 | if (!is_dir($this->arrayConfig['templateDir'])) { 35 | exit("template dir isn't found!"); 36 | } 37 | 38 | if (!is_dir($this->arrayConfig['compileDir'])) { 39 | if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { 40 | mkdir($this->arrayConfig['compileDir']); 41 | } else { 42 | mkdir($this->arrayConfig['compileDir'], 0770, true); 43 | } 44 | } 45 | 46 | } 47 | 48 | public function getPath() 49 | { 50 | $this->arrayConfig['templateDir'] = strstr(realpath($this->arrayConfig['templateDir']), '\\', '/') . '/'; 51 | $this->arrayConfig['compileDir'] = strstr(realpath($this->arrayConfig['compileDir']), '\\', '/') . '/'; 52 | } 53 | 54 | /** 55 | * 取得模板引擎的实例 56 | */ 57 | public static function getInstance() 58 | { 59 | if (is_null(self::$instance)) { 60 | self::$instance = new Template(); 61 | } 62 | return self::$instance; 63 | } 64 | 65 | /** 66 | * 单独设置引擎参数 67 | * 也支持一次性设置多个参数 68 | */ 69 | public function setConfig($key, $value = null) 70 | { 71 | if (is_array($key)) { 72 | $this->arrayConfig = $key + $this->arrayConfig; 73 | } else { 74 | $this->arrayConfig[$key] = $value; 75 | } 76 | } 77 | 78 | /** 79 | * 获取当前模板引擎配置,仅供调试使用 80 | */ 81 | public function getConfig($key = null) 82 | { 83 | if ($key && array_key_exists($key, $this->arrayConfig)) { 84 | return $this->arrayConfig[$key]; 85 | } else { 86 | return $this->arrayConfig; 87 | } 88 | } 89 | 90 | 91 | /** 92 | * 注入单个变量 93 | */ 94 | public function assign($key, $value) 95 | { 96 | $this->value[$key] = $value; 97 | } 98 | 99 | /** 100 | * 注入数组变量 101 | */ 102 | public function assignArray($array) 103 | { 104 | if (is_array($array)) { 105 | foreach ($array as $k => $v) { 106 | $this->value[$k] = $v; 107 | } 108 | } 109 | } 110 | 111 | /** 112 | * 获取模板的位置 113 | * @return [type] [description] 114 | */ 115 | public function path() 116 | { 117 | return $this->arrayConfig['templateDir'] . $this->file . $this->arrayConfig['suffix']; 118 | } 119 | 120 | /** 121 | * 判断配置文件是否要求缓存 122 | */ 123 | public function needCache() 124 | { 125 | return $this->arrayConfig['cache_html']; 126 | } 127 | 128 | /** 129 | * 判断是否需要缓存 130 | */ 131 | public function reCache($file) 132 | { 133 | $flag = false; 134 | $cacheFile = $this->arrayConfig['compileDir'] . md5($file) . $this->arrayConfig['suffix_cache']; 135 | if ($this->arrayConfig['cache_html'] === true) { 136 | //需要缓存 137 | $timeFlag = (time() - @filemtime($cacheFile)) < $this->arrayConfig['cache_time'] ? true : false; 138 | if (is_file($cacheFile) && filesize($cacheFile) > 1 && $timeFlag) { 139 | //缓存存在且未过期 140 | $flag = true; 141 | } else { 142 | $flag = false; 143 | } 144 | } 145 | return $flag; 146 | } 147 | 148 | /** 149 | * 展示模板 150 | */ 151 | public function display($file) 152 | { 153 | $this->file = $file; 154 | echo $this->path()."\n"; 155 | if (!is_file($this->path())) { 156 | exit('找不到对应的模板'); 157 | } 158 | $compileFile = $this->arrayConfig['compileDir'] . md5($file) . '.php'; 159 | $cacheFile = $this->arrayConfig['compileDir'] . md5($file) . $this->arrayConfig['suffix_cache']; 160 | 161 | if ($this->reCache($file) === false) { 162 | //如果需要缓存 163 | $this->debug['cached'] = 'false'; 164 | $this->compileTool = new Compile($this->path(), $compileFile, $this->arrayConfig); 165 | if ($this->needCache()) { 166 | ob_start(); 167 | } 168 | extract($this->value, EXTR_OVERWRITE); 169 | if (!is_file($compileFile) || fileatime($compileFile) < filemtime($this->path())) { 170 | $this->compileTool->value = $this->value; 171 | $this->compileTool->compile(); 172 | include $compileFile; 173 | } else { 174 | include $compileFile; 175 | } 176 | 177 | if ($this->needCache()) { 178 | $message = ob_get_contents(); 179 | file_put_contents($cacheFile, $message); 180 | } 181 | } else { 182 | readfile($cacheFile); 183 | $this->debug['cached'] = 'true'; 184 | } 185 | $this->debug['spend'] = microtime(true) - $this->debug['begin']; 186 | $this->debug['count'] = count($this->value); 187 | $this->debug_info(); 188 | } 189 | 190 | public function debug_info() 191 | { 192 | if ($this->arrayConfig['debug'] === true) { 193 | echo "
", '-------------------- debug_info--------------', "
"; 194 | echo '程序运行日期:', date("Y-m-d h:i:s"), "
"; 195 | echo '模板解析耗时:', $this->debug['spend'], '秒', "
"; 196 | echo '模板包含标签数目:', $this->debug['count'], "
"; 197 | echo '是否使用静态缓存:', $this->debug['cached'], "
"; 198 | echo '模板引擎实例参数:', var_dump($this->getConfig()); 199 | } 200 | } 201 | 202 | /** 203 | * 清楚缓存的html文件 204 | * @return [type] [description] 205 | */ 206 | public function clean() 207 | { 208 | if ($path === null) { 209 | $path = $this->arrayConfig['compileDir']; 210 | $path = glob($path . '* ' . $this->arrayConfig['suffix_cache']); 211 | } else { 212 | $path = $this->arrayConfig['compileDir'] . md5($path) . $this->arrayConfig['suffix_cache']; 213 | } 214 | foreach ((array)$path as $v) { 215 | unlink($v); 216 | } 217 | } 218 | } -------------------------------------------------------------------------------- /Andromeda/core/TemplateEngine/cache/aa08769cdcb26674c6706093503ff0a3.php: -------------------------------------------------------------------------------- 1 | 2 | value['data']; ?>,value['person']; ?> 3 | 7 | "; 9 | ?> 10 | 11 | 成功 12 | 13 | 失败 14 | 15 | 我最厉害value['data']; ?> 16 | 17 | -------------------------------------------------------------------------------- /Andromeda/core/TemplateEngine/template/member.tpl: -------------------------------------------------------------------------------- 1 | {!bootstrap.js!} 2 | {$data},{$person} 3 | 7 | "; 9 | ?> 10 | {if $data === 'a'} 11 | 成功 12 | {elseif $data === 'b'} 13 | 失败 14 | {else} 15 | 我最厉害{$data} 16 | {/if} 17 | {#这里是注释#} -------------------------------------------------------------------------------- /Andromeda/core/TemplateEngine/test.php: -------------------------------------------------------------------------------- 1 | true]); 4 | $tpl->assign('data', 'hello world'); 5 | $tpl->assign('person', 'htGod'); 6 | $tpl->assign('data1', 3); 7 | $arr = array(1,2,3,4,'5',6); 8 | $tpl->assign('b', $arr); 9 | $tpl->display('member'); 10 | -------------------------------------------------------------------------------- /Andromeda/core/Util.class.php: -------------------------------------------------------------------------------- 1 | $param) 31 | { 32 | $tmp[] = $k.'='.$param; 33 | } 34 | $params = implode('&',$tmp); 35 | return $params; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Andromeda/core/View.class.php: -------------------------------------------------------------------------------- 1 | render = $filePath; 36 | 37 | } 38 | } 39 | 40 | /** 41 | * 渲染变量 42 | * assign variable 43 | * @param $variable 44 | * @param string $value 45 | */ 46 | public function assign($variable, $value = '') 47 | { 48 | if (is_array($variable)) { 49 | 50 | $this->data = array_merge($this->data, $variable); 51 | } else { 52 | 53 | $this->data[$variable] = $value; 54 | } 55 | 56 | 57 | } 58 | 59 | /** 60 | * 显示模板 61 | * display tempalte 62 | * @param $template 63 | */ 64 | public function display($template) 65 | { 66 | $data = $this->data; 67 | 68 | $filePath = $template . '.html'; //todo 加配置支持其他后缀的模板 69 | if (file_exists($filePath)) { 70 | 71 | $this->render = $filePath; 72 | 73 | } 74 | 75 | if (isset($this)) { 76 | include($this->render); 77 | } 78 | 79 | } 80 | 81 | 82 | } -------------------------------------------------------------------------------- /Andromeda/core/log/driver/File.php: -------------------------------------------------------------------------------- 1 | 'mysql', 12 | 'DB_HOST' => 'mysql', 13 | 'DB_NAME' => 'andromeda', 14 | 'DB_USER' => 'root', 15 | 'DB_PASSWORD'=> '123456', 16 | 'DB_PORT' => '3306', 17 | 'DB_CHARSET' => 'utf-8', 18 | 'DB_PREFIX' => '' 19 | 20 | ); 21 | -------------------------------------------------------------------------------- /App/Config/loader.php: -------------------------------------------------------------------------------- 1 | registerDirs( 18 | [ 19 | //目录 20 | $config->application->controllersDir, 21 | $config->application->modelsDir 22 | ] 23 | )->register(); 24 | */ 25 | 26 | -------------------------------------------------------------------------------- /App/Config/router.php: -------------------------------------------------------------------------------- 1 | setShared("singletonWriter", function () use ($di, $config) { 17 | $singletonWriter = SingletonWriter::getInstance($di); 18 | return $singletonWriter; 19 | }); 20 | 21 | 22 | //setShared 设置共享实例 23 | $di->setShared("logger", function () use ($di) { 24 | $logger = new Log(); 25 | return $logger; 26 | }); 27 | 28 | //set 设置独享实例,每次调用都会new一个新的对象 29 | $di->set("writer", function () use ($di, $config) { 30 | $write = new Writer($di); 31 | return $write; 32 | }); 33 | 34 | -------------------------------------------------------------------------------- /App/Controllers/Home/BaseController.class.php: -------------------------------------------------------------------------------- 1 | writer->hello(); 20 | $this->writer->hello(); 21 | $this->writer->hello(); 22 | Log::write("hehehehe"); 23 | $this->singletonWriter->hello(); 24 | $this->singletonWriter->hello(); 25 | $this->singletonWriter->hello(); 26 | $this->singletonWriter::staticHello(); 27 | 28 | 29 | } 30 | 31 | public function var() 32 | { 33 | Log::ERR("访问var"); 34 | $this->assign('var', "foobar"); 35 | $this->display('var'); 36 | 37 | } 38 | 39 | public function getUsers() 40 | { 41 | Log::ERR("访问getUser"); 42 | $userModel = new UserModel("user"); 43 | $result = $userModel->getUsers(); 44 | $this->assign('page', 'home/getuser'); 45 | $this->assign('result', $result); 46 | $this->display('getUser'); 47 | 48 | } 49 | 50 | /** 51 | * index.php?p=home&c=Index&a=paramTest&p1=2&p3=3 52 | * @param $p1 53 | * @param int $p2 54 | * @param $p3 55 | */ 56 | public function paramTest($p1, $p2, $p3=22) 57 | { 58 | Log::write("eeeee"); 59 | var_dump($p1); 60 | var_dump($p2); 61 | var_dump($p3); 62 | 63 | } 64 | 65 | public function testTpl() 66 | { 67 | $tpl = new Template(); 68 | $tpl->assign('data', 'hello world'); 69 | $tpl->assign('person', 'htGod'); 70 | $tpl->assign('data1', 3); 71 | $arr = array(1, 2, 3, 4, '5', 6); 72 | $tpl->assign('b', $arr); 73 | $tpl->display('home/member'); 74 | } 75 | 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /App/Models/UserModel.class.php: -------------------------------------------------------------------------------- 1 | table}"; 9 | $user=$this->db->query($sql); 10 | return $user; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /App/Views/admin/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | miniFramework 5 | 6 | 7 | hello this is a miniFramework! 8 | 9 | 10 | -------------------------------------------------------------------------------- /App/Views/home/getUser.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Andromeda php framework 5 | 6 | 7 | hello this is a Andromeda php framework!
8 | now you are visiting the
9 | 10 | 11 | result prase example:
12 | 13 | "; 17 | echo 'user_name:'.$v['name']."
"; 18 | } 19 | 20 | ?> 21 | 22 | -------------------------------------------------------------------------------- /App/Views/home/getUserById.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Andromeda php framework 5 | 6 | 7 |

Hello this is Andromeda php framework!

8 | now you are visiting the
9 | 10 | 11 | 12 | 13 | 14 | 15 | param prase example:
16 | 17 | id=
18 | limit=
19 | 20 | 21 | -------------------------------------------------------------------------------- /App/Views/home/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Andromeda php framework 5 | 6 | 7 |

Hello this is Andromeda php framework!

8 |

you are visiting the page!

9 | 10 | -------------------------------------------------------------------------------- /App/Views/home/var.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Andromeda php framework 5 | 6 | 7 |

Hello this is Andromeda php framework!

8 | 9 | 10 | 11 | 12 | var=
13 | 16 | 17 | -------------------------------------------------------------------------------- /Doc/实现action的参数获取.md: -------------------------------------------------------------------------------- 1 | ###实现从url或者post参数中取出调用action的参数 2 | 3 | 示例代码,取自ThinkPHP3.2.3 4 | 5 | ``` 6 | public static function invokeAction($module,$action){ 7 | if(!preg_match('/^[A-Za-z](\w)*$/',$action)){ 8 | // 非法操作 9 | throw new \ReflectionException(); 10 | } 11 | //执行当前操作 12 | $method = new \ReflectionMethod($module, $action); 13 | if($method->isPublic() && !$method->isStatic()) { 14 | $class = new \ReflectionClass($module); 15 | // 前置操作 16 | if($class->hasMethod('_before_'.$action)) { 17 | $before = $class->getMethod('_before_'.$action); 18 | if($before->isPublic()) { 19 | $before->invoke($module); 20 | } 21 | } 22 | // URL参数绑定检测 23 | if($method->getNumberOfParameters()>0 && C('URL_PARAMS_BIND')){ 24 | switch($_SERVER['REQUEST_METHOD']) { 25 | case 'POST': 26 | $vars = array_merge($_GET,$_POST); 27 | break; 28 | case 'PUT': 29 | parse_str(file_get_contents('php://input'), $vars); 30 | break; 31 | default: 32 | $vars = $_GET; 33 | } 34 | $params = $method->getParameters(); 35 | $paramsBindType = C('URL_PARAMS_BIND_TYPE'); 36 | foreach ($params as $param){ 37 | $name = $param->getName(); 38 | if( 1 == $paramsBindType && !empty($vars) ){ 39 | $args[] = array_shift($vars); 40 | }elseif( 0 == $paramsBindType && isset($vars[$name])){ 41 | $args[] = $vars[$name]; 42 | }elseif($param->isDefaultValueAvailable()){ 43 | $args[] = $param->getDefaultValue(); 44 | }else{ 45 | E(L('_PARAM_ERROR_').':'.$name); 46 | } 47 | } 48 | // 开启绑定参数过滤机制 49 | if(C('URL_PARAMS_SAFE')){ 50 | $filters = C('URL_PARAMS_FILTER')?:C('DEFAULT_FILTER'); 51 | if($filters) { 52 | $filters = explode(',',$filters); 53 | foreach($filters as $filter){ 54 | $args = array_map_recursive($filter,$args); // 参数过滤 55 | } 56 | } 57 | } 58 | array_walk_recursive($args,'think_filter'); 59 | $method->invokeArgs($module,$args); 60 | }else{ 61 | $method->invoke($module); 62 | } 63 | // 后置操作 64 | if($class->hasMethod('_after_'.$action)) { 65 | $after = $class->getMethod('_after_'.$action); 66 | if($after->isPublic()) { 67 | $after->invoke($module); 68 | } 69 | } 70 | }else{ 71 | // 操作方法不是Public 抛出异常 72 | throw new \ReflectionException(); 73 | } 74 | } 75 | 76 | ``` -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Jimmy Lee 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Public/README.md: -------------------------------------------------------------------------------- 1 | #静态文件目录 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | Andromeda is a php framework,apply Di,Ioc. 4 | 5 | # License 6 | [MIT](LICENSE) 7 | 8 | # Quick start 9 | 10 | ```shell 11 | cd Andromeda 12 | composer install 13 | # start server 14 | php -S localhost:8000 15 | # curl or using browser 16 | http://localhost:8000/index.php?p=home&c=index&a=index 17 | http://localhost:8000/index.php?p=home&c=index&a=paramTest&p1=1&p3=2 18 | ``` 19 | 20 | 21 | # Todo 22 | 23 | ## Cache driver 24 | - Redis 25 | - Memcached 26 | - File 27 | 28 | ## Database driver 29 | - MySQL 30 | 31 | ## Log driver 32 | - File 33 | - Elastic search 34 | 35 | 36 | # Dev log 37 | - 2024-06-11:升级依赖包;更新README 38 | - 2017-10-16:实现获取post与get参数结合 39 | - 2017-10-11:准备实现获取post参数 40 | - 2017-10-11:实现获取action参数,以及必填非必填参数判断 41 | - 2017-08-03:下一步实现获取action的参数,利用反射实现 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"jimersylee/andromeda", 3 | "description":"PHP framework", 4 | "type":"framework", 5 | "keywords":[ 6 | "PHP","Framework","PHP Framework" 7 | ], 8 | "require":{ 9 | "php":">=8.0.0", 10 | "filp/whoops": "2.*" 11 | } 12 | } -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "bbc7809637a120d23d46e0947f54205a", 8 | "packages": [ 9 | { 10 | "name": "filp/whoops", 11 | "version": "2.16.0", 12 | "dist": { 13 | "type": "zip", 14 | "url": "https://mirrors.tencent.com/repository/composer/filp/whoops/2.16.0/filp-whoops-2.16.0.zip", 15 | "reference": "befcdc0e5dce67252aa6322d82424be928214fa2", 16 | "shasum": "" 17 | }, 18 | "require": { 19 | "php": "^7.1 || ^8.0", 20 | "psr/log": "^1.0.1 || ^2.0 || ^3.0" 21 | }, 22 | "require-dev": { 23 | "mockery/mockery": "^1.0", 24 | "phpunit/phpunit": "^7.5.20 || ^8.5.8 || ^9.3.3", 25 | "symfony/var-dumper": "^4.0 || ^5.0" 26 | }, 27 | "suggest": { 28 | "symfony/var-dumper": "Pretty print complex values better with var-dumper available", 29 | "whoops/soap": "Formats errors as SOAP responses" 30 | }, 31 | "type": "library", 32 | "extra": { 33 | "branch-alias": { 34 | "dev-master": "2.7-dev" 35 | } 36 | }, 37 | "autoload": { 38 | "psr-4": { 39 | "Whoops\\": "src/Whoops/" 40 | } 41 | }, 42 | "license": [ 43 | "MIT" 44 | ], 45 | "authors": [ 46 | { 47 | "name": "Filipe Dobreira", 48 | "homepage": "https://github.com/filp", 49 | "role": "Developer" 50 | } 51 | ], 52 | "description": "php error handling for cool kids", 53 | "homepage": "https://filp.github.io/whoops/", 54 | "keywords": [ 55 | "error", 56 | "exception", 57 | "handling", 58 | "library", 59 | "throwable", 60 | "whoops" 61 | ], 62 | "time": "2024-09-25T12:00:00+00:00" 63 | }, 64 | { 65 | "name": "psr/log", 66 | "version": "1.1.4", 67 | "source": { 68 | "type": "git", 69 | "url": "https://github.com/php-fig/log.git", 70 | "reference": "d49695b909c3b7628b6289db5479a1c204601f11" 71 | }, 72 | "dist": { 73 | "type": "zip", 74 | "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11", 75 | "reference": "d49695b909c3b7628b6289db5479a1c204601f11", 76 | "shasum": "", 77 | "mirrors": [ 78 | { 79 | "url": "https://mirrors.aliyun.com/composer/dists/%package%/%reference%.%type%", 80 | "preferred": true 81 | } 82 | ] 83 | }, 84 | "require": { 85 | "php": ">=5.3.0" 86 | }, 87 | "type": "library", 88 | "extra": { 89 | "branch-alias": { 90 | "dev-master": "1.1.x-dev" 91 | } 92 | }, 93 | "autoload": { 94 | "psr-4": { 95 | "Psr\\Log\\": "Psr/Log/" 96 | } 97 | }, 98 | "notification-url": "https://packagist.org/downloads/", 99 | "license": [ 100 | "MIT" 101 | ], 102 | "authors": [ 103 | { 104 | "name": "PHP-FIG", 105 | "homepage": "https://www.php-fig.org/" 106 | } 107 | ], 108 | "description": "Common interface for logging libraries", 109 | "homepage": "https://github.com/php-fig/log", 110 | "keywords": [ 111 | "log", 112 | "psr", 113 | "psr-3" 114 | ], 115 | "support": { 116 | "source": "https://github.com/php-fig/log/tree/1.1.4" 117 | }, 118 | "time": "2021-05-03T11:20:27+00:00" 119 | } 120 | ], 121 | "packages-dev": [], 122 | "aliases": [], 123 | "minimum-stability": "stable", 124 | "stability-flags": {}, 125 | "prefer-stable": false, 126 | "prefer-lowest": false, 127 | "platform": { 128 | "php": ">=8.0.0" 129 | }, 130 | "platform-dev": {}, 131 | "plugin-api-version": "2.6.0" 132 | } 133 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | pushHandler(new PrettyPageHandler()); 18 | $whoops->register(); 19 | 20 | 21 | //分隔符 window与linux不同 22 | define("DS", DIRECTORY_SEPARATOR); 23 | 24 | define('ROOT', __DIR__ . DS); 25 | 26 | //echo BASE_PATH; 27 | 28 | define('APP_PATH', ROOT . 'App' . DS);//定义app目录 29 | //echo APP_PATH; 30 | 31 | // 环境常量 32 | define('IS_CLI', PHP_SAPI == 'cli' ? true : false); 33 | 34 | 35 | include ROOT . "/Andromeda/DiInterface.php"; 36 | include ROOT . "/Andromeda/Di.php"; 37 | include ROOT . "/Andromeda/Di/FactoryDefault.php"; 38 | include ROOT . "/Andromeda/Di/InjectionAwareInterface.php"; 39 | include ROOT . "/Andromeda/Di/Injectable.php"; 40 | 41 | include ROOT . "/Andromeda/App.php"; 42 | include ROOT . "/Andromeda/Andromeda.php"; 43 | include ROOT . "/Andromeda/Request.php"; 44 | include ROOT . "/Andromeda/Exception.php"; 45 | 46 | 47 | //容器 48 | $di = new FactoryDefault(); 49 | 50 | 51 | require_once "Andromeda/Andromeda.php"; 52 | include ROOT . "/Andromeda/Mvc/Controller.php"; 53 | 54 | 55 | //载入路由配置 handle routes 56 | 57 | include APP_PATH . "Config/router.php"; 58 | 59 | //载入服务配置 read service 60 | include APP_PATH . "Config/service.php"; 61 | 62 | //载入自动加载配置 63 | include APP_PATH . "Config/loader.php"; 64 | 65 | //应用(组件) 66 | $app = new App($di); 67 | 68 | Andromeda::run($di); 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /test/di/Di.php: -------------------------------------------------------------------------------- 1 | _instances[$name])) { 19 | return $this->_instances[$name]; 20 | } 21 | //检测有没有注册该服务 22 | if (!isset($this->_bindings[$name])) { 23 | return null; 24 | } 25 | $concrete = $this->_bindings[$name]['class'];//对象具体注册内容 26 | $obj = null; 27 | //匿名函数方式 28 | if ($concrete instanceof Closure) { 29 | $obj = call_user_func_array($concrete, $params); 30 | } //字符串方式 31 | elseif (is_string($concrete)) { 32 | if (empty($params)) { 33 | $obj = new $concrete; 34 | } else { //带参数的类实例化,使用反射 35 | $class = new ReflectionClass($concrete); 36 | $obj = $class->newInstanceArgs($params); 37 | } 38 | } //如果是共享服务,则写入_instances列表,下次直接取回 39 | if ($this->_bindings[$name]['shared'] == true && $obj) { 40 | $this->_instances[$name] = $obj; 41 | } 42 | return $obj; 43 | } 44 | 45 | //检测是否已经绑定 46 | public function has($name) 47 | { 48 | return isset($this->_bindings[$name]) or isset($this->_instances[$name]); 49 | } 50 | 51 | //卸载服务 52 | public function remove($name) 53 | { 54 | unset($this->_bindings[$name], $this->_instances[$name]); 55 | } 56 | 57 | //设置服务 58 | public function set($name, $class) 59 | { 60 | $this->_registerService($name, $class); 61 | } 62 | 63 | //设置共享服务 64 | public function setShared($name, $class) 65 | { 66 | $this->_registerService($name, $class, true); 67 | } 68 | 69 | //注册服务 70 | private function _registerService($name, $class, $shared = false) 71 | { 72 | $this->remove($name); 73 | if (!($class instanceof Closure) && is_object($class)) { 74 | $this->_instances[$name] = $class; 75 | } else { 76 | $this->_bindings[$name] = array("class" => $class, "shared" => $shared); 77 | } 78 | } 79 | 80 | //ArrayAccess接口,检测服务是否存在 81 | public function offsetExists($offset) 82 | { 83 | return $this->has($offset); 84 | } 85 | 86 | //ArrayAccess接口,以$di[$name]方式获取服务 87 | public function offsetGet($offset) 88 | { 89 | return $this->get($offset); 90 | } 91 | 92 | //ArrayAccess接口,以$di[$name]=$value方式注册服务,非共享 93 | public function offsetSet($offset, $value) 94 | { 95 | return $this->set($offset, $value); 96 | } 97 | 98 | //ArrayAccess接口,以unset($di[$name])方式卸载服务 99 | public function offsetUnset($offset) 100 | { 101 | return $this->remove($offset); 102 | } 103 | } -------------------------------------------------------------------------------- /test/di/test.php: -------------------------------------------------------------------------------- 1 | name = $name; 24 | } 25 | } 26 | 27 | include "Di.php"; 28 | $di = new Di(); 29 | //匿名函数方式注册一个名为a1的服务 30 | $di->setShared('a1',function($name=""){ 31 | return new A($name); 32 | }); 33 | //直接以类名方式注册 34 | $di->set('a2','A'); 35 | //直接传入实例化的对象 36 | $di->set('a3',new A("小唐")); 37 | 38 | $a1 = $di->get('a1',array("小李")); 39 | echo $a1->name."
";//小李 40 | $a1_1 = $di->get('a1',array("小王")); 41 | echo $a1->name."
";//小李 42 | echo $a1_1->name."
";//小李 43 | 44 | $a2 = $di->get('a2',array("小张")); 45 | echo $a2->name."
";//小张 46 | $a2_1 = $di->get('a2',array("小徐")); 47 | echo $a2->name."
";//小张 48 | echo $a2_1->name."
";//小徐 49 | 50 | $a3 = $di['a3'];//可以直接通过数组方式获取服务对象 51 | echo $a3->name."
";//小唐 -------------------------------------------------------------------------------- /test/namespace/NameSpaceClass.php: -------------------------------------------------------------------------------- 1 |