1 | <?php |
||||||
2 | // +---------------------------------------------------------------------- |
||||||
3 | // | ThinkPHP [ WE CAN DO IT JUST THINK ] |
||||||
4 | // +---------------------------------------------------------------------- |
||||||
5 | // | Copyright (c) 2006~2021 http://thinkphp.cn All rights reserved. |
||||||
6 | // +---------------------------------------------------------------------- |
||||||
7 | // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) |
||||||
8 | // +---------------------------------------------------------------------- |
||||||
9 | // | Author: liu21st <[email protected]> |
||||||
10 | // +---------------------------------------------------------------------- |
||||||
11 | declare (strict_types = 1); |
||||||
12 | |||||||
13 | namespace think; |
||||||
14 | |||||||
15 | use ArrayAccess; |
||||||
16 | use think\facade\Lang; |
||||||
0 ignored issues
–
show
|
|||||||
17 | use think\file\UploadedFile; |
||||||
18 | use think\route\Rule; |
||||||
19 | |||||||
20 | /** |
||||||
21 | * 请求管理类 |
||||||
22 | * @package think |
||||||
23 | */ |
||||||
24 | class Request implements ArrayAccess |
||||||
25 | { |
||||||
26 | /** |
||||||
27 | * 兼容PATH_INFO获取 |
||||||
28 | * @var array |
||||||
29 | */ |
||||||
30 | protected $pathinfoFetch = ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL']; |
||||||
31 | |||||||
32 | /** |
||||||
33 | * PATHINFO变量名 用于兼容模式 |
||||||
34 | * @var string |
||||||
35 | */ |
||||||
36 | protected $varPathinfo = 's'; |
||||||
37 | |||||||
38 | /** |
||||||
39 | * 请求类型 |
||||||
40 | * @var string |
||||||
41 | */ |
||||||
42 | protected $varMethod = '_method'; |
||||||
43 | |||||||
44 | /** |
||||||
45 | * 表单ajax伪装变量 |
||||||
46 | * @var string |
||||||
47 | */ |
||||||
48 | protected $varAjax = '_ajax'; |
||||||
49 | |||||||
50 | /** |
||||||
51 | * 表单pjax伪装变量 |
||||||
52 | * @var string |
||||||
53 | */ |
||||||
54 | protected $varPjax = '_pjax'; |
||||||
55 | |||||||
56 | /** |
||||||
57 | * 域名根 |
||||||
58 | * @var string |
||||||
59 | */ |
||||||
60 | protected $rootDomain = ''; |
||||||
61 | |||||||
62 | /** |
||||||
63 | * HTTPS代理标识 |
||||||
64 | * @var string |
||||||
65 | */ |
||||||
66 | protected $httpsAgentName = ''; |
||||||
67 | |||||||
68 | /** |
||||||
69 | * 前端代理服务器IP |
||||||
70 | * @var array |
||||||
71 | */ |
||||||
72 | protected $proxyServerIp = []; |
||||||
73 | |||||||
74 | /** |
||||||
75 | * 前端代理服务器真实IP头 |
||||||
76 | * @var array |
||||||
77 | */ |
||||||
78 | protected $proxyServerIpHeader = ['HTTP_X_REAL_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_CLIENT_IP', 'HTTP_X_CLIENT_IP', 'HTTP_X_CLUSTER_CLIENT_IP']; |
||||||
79 | |||||||
80 | /** |
||||||
81 | * 请求类型 |
||||||
82 | * @var string |
||||||
83 | */ |
||||||
84 | protected $method; |
||||||
85 | |||||||
86 | /** |
||||||
87 | * 域名(含协议及端口) |
||||||
88 | * @var string |
||||||
89 | */ |
||||||
90 | protected $domain; |
||||||
91 | |||||||
92 | /** |
||||||
93 | * HOST(含端口) |
||||||
94 | * @var string |
||||||
95 | */ |
||||||
96 | protected $host; |
||||||
97 | |||||||
98 | /** |
||||||
99 | * 子域名 |
||||||
100 | * @var string |
||||||
101 | */ |
||||||
102 | protected $subDomain; |
||||||
103 | |||||||
104 | /** |
||||||
105 | * 泛域名 |
||||||
106 | * @var string |
||||||
107 | */ |
||||||
108 | protected $panDomain; |
||||||
109 | |||||||
110 | /** |
||||||
111 | * 当前URL地址 |
||||||
112 | * @var string |
||||||
113 | */ |
||||||
114 | protected $url; |
||||||
115 | |||||||
116 | /** |
||||||
117 | * 基础URL |
||||||
118 | * @var string |
||||||
119 | */ |
||||||
120 | protected $baseUrl; |
||||||
121 | |||||||
122 | /** |
||||||
123 | * 当前执行的文件 |
||||||
124 | * @var string |
||||||
125 | */ |
||||||
126 | protected $baseFile; |
||||||
127 | |||||||
128 | /** |
||||||
129 | * 访问的ROOT地址 |
||||||
130 | * @var string |
||||||
131 | */ |
||||||
132 | protected $root; |
||||||
133 | |||||||
134 | /** |
||||||
135 | * pathinfo |
||||||
136 | * @var string |
||||||
137 | */ |
||||||
138 | protected $pathinfo; |
||||||
139 | |||||||
140 | /** |
||||||
141 | * pathinfo(不含后缀) |
||||||
142 | * @var string |
||||||
143 | */ |
||||||
144 | protected $path; |
||||||
145 | |||||||
146 | /** |
||||||
147 | * 当前请求的IP地址 |
||||||
148 | * @var string |
||||||
149 | */ |
||||||
150 | protected $realIP; |
||||||
151 | |||||||
152 | /** |
||||||
153 | * 当前控制器名 |
||||||
154 | * @var string |
||||||
155 | */ |
||||||
156 | protected $controller; |
||||||
157 | |||||||
158 | /** |
||||||
159 | * 当前操作名 |
||||||
160 | * @var string |
||||||
161 | */ |
||||||
162 | protected $action; |
||||||
163 | |||||||
164 | /** |
||||||
165 | * 当前请求参数 |
||||||
166 | * @var array |
||||||
167 | */ |
||||||
168 | protected $param = []; |
||||||
169 | |||||||
170 | /** |
||||||
171 | * 当前GET参数 |
||||||
172 | * @var array |
||||||
173 | */ |
||||||
174 | protected $get = []; |
||||||
175 | |||||||
176 | /** |
||||||
177 | * 当前POST参数 |
||||||
178 | * @var array |
||||||
179 | */ |
||||||
180 | protected $post = []; |
||||||
181 | |||||||
182 | /** |
||||||
183 | * 当前REQUEST参数 |
||||||
184 | * @var array |
||||||
185 | */ |
||||||
186 | protected $request = []; |
||||||
187 | |||||||
188 | /** |
||||||
189 | * 当前路由对象 |
||||||
190 | * @var Rule |
||||||
191 | */ |
||||||
192 | protected $rule; |
||||||
193 | |||||||
194 | /** |
||||||
195 | * 当前ROUTE参数 |
||||||
196 | * @var array |
||||||
197 | */ |
||||||
198 | protected $route = []; |
||||||
199 | |||||||
200 | /** |
||||||
201 | * 中间件传递的参数 |
||||||
202 | * @var array |
||||||
203 | */ |
||||||
204 | protected $middleware = []; |
||||||
205 | |||||||
206 | /** |
||||||
207 | * 当前PUT参数 |
||||||
208 | * @var array |
||||||
209 | */ |
||||||
210 | protected $put; |
||||||
211 | |||||||
212 | /** |
||||||
213 | * SESSION对象 |
||||||
214 | * @var Session |
||||||
215 | */ |
||||||
216 | protected $session; |
||||||
217 | |||||||
218 | /** |
||||||
219 | * COOKIE数据 |
||||||
220 | * @var array |
||||||
221 | */ |
||||||
222 | protected $cookie = []; |
||||||
223 | |||||||
224 | /** |
||||||
225 | * ENV对象 |
||||||
226 | * @var Env |
||||||
227 | */ |
||||||
228 | protected $env; |
||||||
229 | |||||||
230 | /** |
||||||
231 | * 当前SERVER参数 |
||||||
232 | * @var array |
||||||
233 | */ |
||||||
234 | protected $server = []; |
||||||
235 | |||||||
236 | /** |
||||||
237 | * 当前FILE参数 |
||||||
238 | * @var array |
||||||
239 | */ |
||||||
240 | protected $file = []; |
||||||
241 | |||||||
242 | /** |
||||||
243 | * 当前HEADER参数 |
||||||
244 | * @var array |
||||||
245 | */ |
||||||
246 | protected $header = []; |
||||||
247 | |||||||
248 | /** |
||||||
249 | * 资源类型定义 |
||||||
250 | * @var array |
||||||
251 | */ |
||||||
252 | protected $mimeType = [ |
||||||
253 | 'xml' => 'application/xml,text/xml,application/x-xml', |
||||||
254 | 'json' => 'application/json,text/x-json,application/jsonrequest,text/json', |
||||||
255 | 'js' => 'text/javascript,application/javascript,application/x-javascript', |
||||||
256 | 'css' => 'text/css', |
||||||
257 | 'rss' => 'application/rss+xml', |
||||||
258 | 'yaml' => 'application/x-yaml,text/yaml', |
||||||
259 | 'atom' => 'application/atom+xml', |
||||||
260 | 'pdf' => 'application/pdf', |
||||||
261 | 'text' => 'text/plain', |
||||||
262 | 'image' => 'image/png,image/jpg,image/jpeg,image/pjpeg,image/gif,image/webp,image/*', |
||||||
263 | 'csv' => 'text/csv', |
||||||
264 | 'html' => 'text/html,application/xhtml+xml,*/*', |
||||||
265 | ]; |
||||||
266 | |||||||
267 | /** |
||||||
268 | * 当前请求内容 |
||||||
269 | * @var string |
||||||
270 | */ |
||||||
271 | protected $content; |
||||||
272 | |||||||
273 | /** |
||||||
274 | * 全局过滤规则 |
||||||
275 | * @var array |
||||||
276 | */ |
||||||
277 | protected $filter; |
||||||
278 | |||||||
279 | /** |
||||||
280 | * php://input内容 |
||||||
281 | * @var string |
||||||
282 | */ |
||||||
283 | // php://input |
||||||
284 | protected $input; |
||||||
285 | |||||||
286 | /** |
||||||
287 | * 请求安全Key |
||||||
288 | * @var string |
||||||
289 | */ |
||||||
290 | protected $secureKey; |
||||||
291 | |||||||
292 | /** |
||||||
293 | * 是否合并Param |
||||||
294 | * @var bool |
||||||
295 | */ |
||||||
296 | protected $mergeParam = false; |
||||||
297 | |||||||
298 | /** |
||||||
299 | * 架构函数 |
||||||
300 | * @access public |
||||||
301 | 30 | */ |
|||||
302 | public function __construct() |
||||||
303 | { |
||||||
304 | 30 | // 保存 php://input |
|||||
305 | 30 | $this->input = file_get_contents('php://input'); |
|||||
306 | } |
||||||
307 | 30 | ||||||
308 | public static function __make(App $app) |
||||||
309 | 30 | { |
|||||
310 | $request = new static(); |
||||||
311 | 30 | ||||||
312 | if (function_exists('apache_request_headers') && $result = apache_request_headers()) { |
||||||
313 | $header = $result; |
||||||
314 | 30 | } else { |
|||||
315 | 30 | $header = []; |
|||||
316 | 30 | $server = $_SERVER; |
|||||
317 | 30 | foreach ($server as $key => $val) { |
|||||
318 | if (0 === strpos($key, 'HTTP_')) { |
||||||
319 | 10 | $key = str_replace('_', '-', strtolower(substr($key, 5))); |
|||||
320 | $header[$key] = $val; |
||||||
321 | } |
||||||
322 | 30 | } |
|||||
323 | if (isset($server['CONTENT_TYPE'])) { |
||||||
324 | $header['content-type'] = $server['CONTENT_TYPE']; |
||||||
325 | 30 | } |
|||||
326 | if (isset($server['CONTENT_LENGTH'])) { |
||||||
327 | $header['content-length'] = $server['CONTENT_LENGTH']; |
||||||
328 | } |
||||||
329 | } |
||||||
330 | 30 | ||||||
331 | 30 | $request->header = array_change_key_case($header); |
|||||
0 ignored issues
–
show
It seems like
$header can also be of type true ; however, parameter $array of array_change_key_case() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
332 | 30 | $request->server = $_SERVER; |
|||||
333 | $request->env = $app->env; |
||||||
334 | 30 | ||||||
335 | $inputData = $request->getInputData($request->input); |
||||||
336 | 30 | ||||||
337 | 30 | $request->get = $_GET; |
|||||
338 | 30 | $request->post = $_POST ?: $inputData; |
|||||
339 | 30 | $request->put = $inputData; |
|||||
340 | 30 | $request->request = $_REQUEST; |
|||||
341 | 30 | $request->cookie = $_COOKIE; |
|||||
342 | $request->file = $_FILES ?? []; |
||||||
343 | 30 | ||||||
344 | return $request; |
||||||
345 | } |
||||||
346 | |||||||
347 | /** |
||||||
348 | * 设置当前包含协议的域名 |
||||||
349 | * @access public |
||||||
350 | * @param string $domain 域名 |
||||||
351 | * @return $this |
||||||
352 | */ |
||||||
353 | public function setDomain(string $domain) |
||||||
354 | { |
||||||
355 | $this->domain = $domain; |
||||||
356 | return $this; |
||||||
357 | } |
||||||
358 | |||||||
359 | /** |
||||||
360 | * 获取当前包含协议的域名 |
||||||
361 | * @access public |
||||||
362 | * @param bool $port 是否需要去除端口号 |
||||||
363 | * @return string |
||||||
364 | */ |
||||||
365 | public function domain(bool $port = false): string |
||||||
366 | { |
||||||
367 | return $this->scheme() . '://' . $this->host($port); |
||||||
368 | } |
||||||
369 | |||||||
370 | /** |
||||||
371 | * 获取当前根域名 |
||||||
372 | * @access public |
||||||
373 | * @return string |
||||||
374 | 33 | */ |
|||||
375 | public function rootDomain(): string |
||||||
376 | 33 | { |
|||||
377 | $root = $this->rootDomain; |
||||||
378 | 33 | ||||||
379 | 33 | if (!$root) { |
|||||
380 | 33 | $item = explode('.', $this->host()); |
|||||
381 | 33 | $count = count($item); |
|||||
382 | $root = $count > 1 ? $item[$count - 2] . '.' . $item[$count - 1] : $item[0]; |
||||||
383 | } |
||||||
384 | 33 | ||||||
385 | return $root; |
||||||
386 | } |
||||||
387 | |||||||
388 | /** |
||||||
389 | * 设置当前泛域名的值 |
||||||
390 | * @access public |
||||||
391 | * @param string $domain 域名 |
||||||
392 | * @return $this |
||||||
393 | */ |
||||||
394 | public function setSubDomain(string $domain) |
||||||
395 | { |
||||||
396 | $this->subDomain = $domain; |
||||||
397 | return $this; |
||||||
398 | } |
||||||
399 | |||||||
400 | /** |
||||||
401 | * 获取当前子域名 |
||||||
402 | * @access public |
||||||
403 | * @return string |
||||||
404 | 33 | */ |
|||||
405 | public function subDomain(): string |
||||||
406 | 33 | { |
|||||
407 | if (is_null($this->subDomain)) { |
||||||
0 ignored issues
–
show
|
|||||||
408 | 33 | // 获取当前主域名 |
|||||
409 | $rootDomain = $this->rootDomain(); |
||||||
410 | 33 | ||||||
411 | 33 | if ($rootDomain) { |
|||||
412 | 33 | $sub = stristr($this->host(), $rootDomain, true); |
|||||
413 | $this->subDomain = $sub ? rtrim($sub, '.') : ''; |
||||||
414 | } else { |
||||||
415 | $this->subDomain = ''; |
||||||
416 | } |
||||||
417 | } |
||||||
418 | 33 | ||||||
419 | return $this->subDomain; |
||||||
420 | } |
||||||
421 | |||||||
422 | /** |
||||||
423 | * 设置当前泛域名的值 |
||||||
424 | * @access public |
||||||
425 | * @param string $domain 域名 |
||||||
426 | * @return $this |
||||||
427 | */ |
||||||
428 | public function setPanDomain(string $domain) |
||||||
429 | { |
||||||
430 | $this->panDomain = $domain; |
||||||
431 | return $this; |
||||||
432 | } |
||||||
433 | |||||||
434 | /** |
||||||
435 | * 获取当前泛域名的值 |
||||||
436 | * @access public |
||||||
437 | * @return string |
||||||
438 | 3 | */ |
|||||
439 | public function panDomain(): string |
||||||
440 | 3 | { |
|||||
441 | return $this->panDomain ?: ''; |
||||||
442 | } |
||||||
443 | |||||||
444 | /** |
||||||
445 | * 设置当前完整URL 包括QUERY_STRING |
||||||
446 | * @access public |
||||||
447 | * @param string $url URL地址 |
||||||
448 | * @return $this |
||||||
449 | */ |
||||||
450 | public function setUrl(string $url) |
||||||
451 | { |
||||||
452 | $this->url = $url; |
||||||
453 | return $this; |
||||||
454 | } |
||||||
455 | |||||||
456 | /** |
||||||
457 | * 获取当前完整URL 包括QUERY_STRING |
||||||
458 | * @access public |
||||||
459 | * @param bool $complete 是否包含完整域名 |
||||||
460 | * @return string |
||||||
461 | */ |
||||||
462 | public function url(bool $complete = false): string |
||||||
463 | { |
||||||
464 | if ($this->url) { |
||||||
465 | $url = $this->url; |
||||||
466 | } elseif ($this->server('HTTP_X_REWRITE_URL')) { |
||||||
467 | $url = $this->server('HTTP_X_REWRITE_URL'); |
||||||
468 | } elseif ($this->server('REQUEST_URI')) { |
||||||
469 | $url = $this->server('REQUEST_URI'); |
||||||
470 | } elseif ($this->server('ORIG_PATH_INFO')) { |
||||||
471 | $url = $this->server('ORIG_PATH_INFO') . (!empty($this->server('QUERY_STRING')) ? '?' . $this->server('QUERY_STRING') : ''); |
||||||
472 | } elseif (isset($_SERVER['argv'][1])) { |
||||||
473 | $url = $_SERVER['argv'][1]; |
||||||
474 | } else { |
||||||
475 | $url = ''; |
||||||
476 | } |
||||||
477 | |||||||
478 | return $complete ? $this->domain() . $url : $url; |
||||||
479 | } |
||||||
480 | |||||||
481 | /** |
||||||
482 | * 设置当前URL 不含QUERY_STRING |
||||||
483 | * @access public |
||||||
484 | * @param string $url URL地址 |
||||||
485 | * @return $this |
||||||
486 | */ |
||||||
487 | public function setBaseUrl(string $url) |
||||||
488 | { |
||||||
489 | $this->baseUrl = $url; |
||||||
490 | return $this; |
||||||
491 | } |
||||||
492 | |||||||
493 | /** |
||||||
494 | * 获取当前URL 不含QUERY_STRING |
||||||
495 | * @access public |
||||||
496 | * @param bool $complete 是否包含完整域名 |
||||||
497 | * @return string |
||||||
498 | */ |
||||||
499 | public function baseUrl(bool $complete = false): string |
||||||
500 | { |
||||||
501 | if (!$this->baseUrl) { |
||||||
502 | $str = $this->url(); |
||||||
503 | $this->baseUrl = strpos($str, '?') ? strstr($str, '?', true) : $str; |
||||||
504 | } |
||||||
505 | |||||||
506 | return $complete ? $this->domain() . $this->baseUrl : $this->baseUrl; |
||||||
507 | } |
||||||
508 | |||||||
509 | /** |
||||||
510 | * 获取当前执行的文件 SCRIPT_NAME |
||||||
511 | * @access public |
||||||
512 | * @param bool $complete 是否包含完整域名 |
||||||
513 | * @return string |
||||||
514 | */ |
||||||
515 | public function baseFile(bool $complete = false): string |
||||||
516 | { |
||||||
517 | if (!$this->baseFile) { |
||||||
518 | $url = ''; |
||||||
519 | if (!$this->isCli()) { |
||||||
520 | $script_name = basename($this->server('SCRIPT_FILENAME')); |
||||||
521 | if (basename($this->server('SCRIPT_NAME')) === $script_name) { |
||||||
522 | $url = $this->server('SCRIPT_NAME'); |
||||||
523 | } elseif (basename($this->server('PHP_SELF')) === $script_name) { |
||||||
524 | $url = $this->server('PHP_SELF'); |
||||||
525 | } elseif (basename($this->server('ORIG_SCRIPT_NAME')) === $script_name) { |
||||||
526 | $url = $this->server('ORIG_SCRIPT_NAME'); |
||||||
527 | } elseif (($pos = strpos($this->server('PHP_SELF'), '/' . $script_name)) !== false) { |
||||||
528 | $url = substr($this->server('SCRIPT_NAME'), 0, $pos) . '/' . $script_name; |
||||||
529 | } elseif ($this->server('DOCUMENT_ROOT') && strpos($this->server('SCRIPT_FILENAME'), $this->server('DOCUMENT_ROOT')) === 0) { |
||||||
530 | $url = str_replace('\\', '/', str_replace($this->server('DOCUMENT_ROOT'), '', $this->server('SCRIPT_FILENAME'))); |
||||||
531 | } |
||||||
532 | } |
||||||
533 | $this->baseFile = $url; |
||||||
534 | } |
||||||
535 | |||||||
536 | return $complete ? $this->domain() . $this->baseFile : $this->baseFile; |
||||||
537 | } |
||||||
538 | |||||||
539 | /** |
||||||
540 | * 设置URL访问根地址 |
||||||
541 | * @access public |
||||||
542 | * @param string $url URL地址 |
||||||
543 | * @return $this |
||||||
544 | */ |
||||||
545 | public function setRoot(string $url) |
||||||
546 | { |
||||||
547 | $this->root = $url; |
||||||
548 | return $this; |
||||||
549 | } |
||||||
550 | |||||||
551 | /** |
||||||
552 | * 获取URL访问根地址 |
||||||
553 | * @access public |
||||||
554 | * @param bool $complete 是否包含完整域名 |
||||||
555 | * @return string |
||||||
556 | */ |
||||||
557 | public function root(bool $complete = false): string |
||||||
558 | { |
||||||
559 | if (!$this->root) { |
||||||
560 | $file = $this->baseFile(); |
||||||
561 | if ($file && 0 !== strpos($this->url(), $file)) { |
||||||
562 | $file = str_replace('\\', '/', dirname($file)); |
||||||
563 | } |
||||||
564 | $this->root = rtrim($file, '/'); |
||||||
565 | } |
||||||
566 | |||||||
567 | return $complete ? $this->domain() . $this->root : $this->root; |
||||||
568 | } |
||||||
569 | |||||||
570 | /** |
||||||
571 | * 获取URL访问根目录 |
||||||
572 | * @access public |
||||||
573 | * @return string |
||||||
574 | */ |
||||||
575 | public function rootUrl(): string |
||||||
576 | { |
||||||
577 | $base = $this->root(); |
||||||
578 | $root = strpos($base, '.') ? ltrim(dirname($base), DIRECTORY_SEPARATOR) : $base; |
||||||
579 | |||||||
580 | if ('' != $root) { |
||||||
581 | $root = '/' . ltrim($root, '/'); |
||||||
582 | } |
||||||
583 | |||||||
584 | return $root; |
||||||
585 | } |
||||||
586 | |||||||
587 | /** |
||||||
588 | * 设置当前请求的pathinfo |
||||||
589 | * @access public |
||||||
590 | * @param string $pathinfo |
||||||
591 | * @return $this |
||||||
592 | */ |
||||||
593 | public function setPathinfo(string $pathinfo) |
||||||
594 | { |
||||||
595 | $this->pathinfo = $pathinfo; |
||||||
596 | return $this; |
||||||
597 | } |
||||||
598 | |||||||
599 | /** |
||||||
600 | * 获取当前请求URL的pathinfo信息(含URL后缀) |
||||||
601 | * @access public |
||||||
602 | * @return string |
||||||
603 | */ |
||||||
604 | public function pathinfo(): string |
||||||
605 | { |
||||||
606 | if (is_null($this->pathinfo)) { |
||||||
0 ignored issues
–
show
|
|||||||
607 | if (isset($_GET[$this->varPathinfo])) { |
||||||
608 | // 判断URL里面是否有兼容模式参数 |
||||||
609 | $pathinfo = $_GET[$this->varPathinfo]; |
||||||
610 | unset($_GET[$this->varPathinfo]); |
||||||
611 | unset($this->get[$this->varPathinfo]); |
||||||
612 | } elseif ($this->server('PATH_INFO')) { |
||||||
613 | $pathinfo = $this->server('PATH_INFO'); |
||||||
614 | } elseif (false !== strpos(PHP_SAPI, 'cli')) { |
||||||
615 | $pathinfo = strpos($this->server('REQUEST_URI'), '?') ? strstr($this->server('REQUEST_URI'), '?', true) : $this->server('REQUEST_URI'); |
||||||
616 | } |
||||||
617 | |||||||
618 | // 分析PATHINFO信息 |
||||||
619 | if (!isset($pathinfo)) { |
||||||
620 | foreach ($this->pathinfoFetch as $type) { |
||||||
621 | if ($this->server($type)) { |
||||||
622 | $pathinfo = (0 === strpos($this->server($type), $this->server('SCRIPT_NAME'))) ? |
||||||
623 | substr($this->server($type), strlen($this->server('SCRIPT_NAME'))) : $this->server($type); |
||||||
624 | break; |
||||||
625 | } |
||||||
626 | } |
||||||
627 | } |
||||||
628 | |||||||
629 | if (!empty($pathinfo)) { |
||||||
630 | unset($this->get[$pathinfo], $this->request[$pathinfo]); |
||||||
631 | } |
||||||
632 | |||||||
633 | $this->pathinfo = empty($pathinfo) || '/' == $pathinfo ? '' : ltrim($pathinfo, '/'); |
||||||
634 | } |
||||||
635 | |||||||
636 | return $this->pathinfo; |
||||||
637 | } |
||||||
638 | |||||||
639 | /** |
||||||
640 | * 当前URL的访问后缀 |
||||||
641 | * @access public |
||||||
642 | * @return string |
||||||
643 | */ |
||||||
644 | public function ext(): string |
||||||
645 | { |
||||||
646 | return pathinfo($this->pathinfo(), PATHINFO_EXTENSION); |
||||||
647 | } |
||||||
648 | |||||||
649 | /** |
||||||
650 | * 获取当前请求的时间 |
||||||
651 | * @access public |
||||||
652 | * @param bool $float 是否使用浮点类型 |
||||||
653 | * @return integer|float |
||||||
654 | */ |
||||||
655 | public function time(bool $float = false) |
||||||
656 | { |
||||||
657 | return $float ? $this->server('REQUEST_TIME_FLOAT') : $this->server('REQUEST_TIME'); |
||||||
658 | } |
||||||
659 | |||||||
660 | /** |
||||||
661 | * 当前请求的资源类型 |
||||||
662 | * @access public |
||||||
663 | * @return string |
||||||
664 | 21 | */ |
|||||
665 | public function type(): string |
||||||
666 | 21 | { |
|||||
667 | $accept = $this->server('HTTP_ACCEPT'); |
||||||
668 | 21 | ||||||
669 | 21 | if (empty($accept)) { |
|||||
670 | return ''; |
||||||
671 | } |
||||||
672 | |||||||
673 | foreach ($this->mimeType as $key => $val) { |
||||||
674 | $array = explode(',', $val); |
||||||
675 | foreach ($array as $k => $v) { |
||||||
676 | if (stristr($accept, $v)) { |
||||||
677 | return $key; |
||||||
678 | } |
||||||
679 | } |
||||||
680 | } |
||||||
681 | |||||||
682 | return ''; |
||||||
683 | } |
||||||
684 | |||||||
685 | /** |
||||||
686 | * 设置资源类型 |
||||||
687 | * @access public |
||||||
688 | * @param string|array $type 资源类型名 |
||||||
689 | * @param string $val 资源类型 |
||||||
690 | * @return void |
||||||
691 | */ |
||||||
692 | public function mimeType($type, $val = ''): void |
||||||
693 | { |
||||||
694 | if (is_array($type)) { |
||||||
695 | $this->mimeType = array_merge($this->mimeType, $type); |
||||||
696 | } else { |
||||||
697 | $this->mimeType[$type] = $val; |
||||||
698 | } |
||||||
699 | } |
||||||
700 | |||||||
701 | /** |
||||||
702 | * 设置请求类型 |
||||||
703 | * @access public |
||||||
704 | * @param string $method 请求类型 |
||||||
705 | * @return $this |
||||||
706 | */ |
||||||
707 | public function setMethod(string $method) |
||||||
708 | { |
||||||
709 | $this->method = strtoupper($method); |
||||||
710 | return $this; |
||||||
711 | } |
||||||
712 | |||||||
713 | /** |
||||||
714 | * 当前的请求类型 |
||||||
715 | * @access public |
||||||
716 | * @param bool $origin 是否获取原始请求类型 |
||||||
717 | * @return string |
||||||
718 | */ |
||||||
719 | public function method(bool $origin = false): string |
||||||
720 | { |
||||||
721 | if ($origin) { |
||||||
722 | // 获取原始请求类型 |
||||||
723 | return $this->server('REQUEST_METHOD') ?: 'GET'; |
||||||
724 | } elseif (!$this->method) { |
||||||
725 | if (isset($this->post[$this->varMethod])) { |
||||||
726 | $method = strtolower($this->post[$this->varMethod]); |
||||||
727 | if (in_array($method, ['get', 'post', 'put', 'patch', 'delete'])) { |
||||||
728 | $this->method = strtoupper($method); |
||||||
729 | $this->{$method} = $this->post; |
||||||
730 | } else { |
||||||
731 | $this->method = 'POST'; |
||||||
732 | } |
||||||
733 | unset($this->post[$this->varMethod]); |
||||||
734 | } elseif ($this->server('HTTP_X_HTTP_METHOD_OVERRIDE')) { |
||||||
735 | $this->method = strtoupper($this->server('HTTP_X_HTTP_METHOD_OVERRIDE')); |
||||||
736 | } else { |
||||||
737 | $this->method = $this->server('REQUEST_METHOD') ?: 'GET'; |
||||||
738 | } |
||||||
739 | } |
||||||
740 | |||||||
741 | return $this->method; |
||||||
742 | } |
||||||
743 | |||||||
744 | /** |
||||||
745 | * 是否为GET请求 |
||||||
746 | * @access public |
||||||
747 | * @return bool |
||||||
748 | */ |
||||||
749 | public function isGet(): bool |
||||||
750 | { |
||||||
751 | return $this->method() == 'GET'; |
||||||
752 | } |
||||||
753 | |||||||
754 | /** |
||||||
755 | * 是否为POST请求 |
||||||
756 | * @access public |
||||||
757 | * @return bool |
||||||
758 | */ |
||||||
759 | public function isPost(): bool |
||||||
760 | { |
||||||
761 | return $this->method() == 'POST'; |
||||||
762 | } |
||||||
763 | |||||||
764 | /** |
||||||
765 | * 是否为PUT请求 |
||||||
766 | * @access public |
||||||
767 | * @return bool |
||||||
768 | */ |
||||||
769 | public function isPut(): bool |
||||||
770 | { |
||||||
771 | return $this->method() == 'PUT'; |
||||||
772 | } |
||||||
773 | |||||||
774 | /** |
||||||
775 | * 是否为DELTE请求 |
||||||
776 | * @access public |
||||||
777 | * @return bool |
||||||
778 | */ |
||||||
779 | public function isDelete(): bool |
||||||
780 | { |
||||||
781 | return $this->method() == 'DELETE'; |
||||||
782 | } |
||||||
783 | |||||||
784 | /** |
||||||
785 | * 是否为HEAD请求 |
||||||
786 | * @access public |
||||||
787 | * @return bool |
||||||
788 | */ |
||||||
789 | public function isHead(): bool |
||||||
790 | { |
||||||
791 | return $this->method() == 'HEAD'; |
||||||
792 | } |
||||||
793 | |||||||
794 | /** |
||||||
795 | * 是否为PATCH请求 |
||||||
796 | * @access public |
||||||
797 | * @return bool |
||||||
798 | */ |
||||||
799 | public function isPatch(): bool |
||||||
800 | { |
||||||
801 | return $this->method() == 'PATCH'; |
||||||
802 | } |
||||||
803 | |||||||
804 | /** |
||||||
805 | * 是否为OPTIONS请求 |
||||||
806 | * @access public |
||||||
807 | * @return bool |
||||||
808 | */ |
||||||
809 | public function isOptions(): bool |
||||||
810 | { |
||||||
811 | return $this->method() == 'OPTIONS'; |
||||||
812 | } |
||||||
813 | |||||||
814 | /** |
||||||
815 | * 是否为cli |
||||||
816 | * @access public |
||||||
817 | * @return bool |
||||||
818 | */ |
||||||
819 | public function isCli(): bool |
||||||
820 | { |
||||||
821 | return PHP_SAPI == 'cli'; |
||||||
822 | } |
||||||
823 | |||||||
824 | /** |
||||||
825 | * 是否为cgi |
||||||
826 | * @access public |
||||||
827 | * @return bool |
||||||
828 | */ |
||||||
829 | public function isCgi(): bool |
||||||
830 | { |
||||||
831 | return strpos(PHP_SAPI, 'cgi') === 0; |
||||||
832 | } |
||||||
833 | |||||||
834 | /** |
||||||
835 | * 获取当前请求的参数 |
||||||
836 | * @access public |
||||||
837 | * @param string|array $name 变量名 |
||||||
838 | * @param mixed $default 默认值 |
||||||
839 | * @param string|array $filter 过滤方法 |
||||||
840 | * @return mixed |
||||||
841 | 33 | */ |
|||||
842 | public function param($name = '', $default = null, $filter = '') |
||||||
843 | 33 | { |
|||||
844 | 33 | if (empty($this->mergeParam)) { |
|||||
845 | $method = $this->method(true); |
||||||
846 | |||||||
847 | 22 | // 自动获取请求变量 |
|||||
848 | 33 | switch ($method) { |
|||||
849 | 3 | case 'POST': |
|||||
850 | 3 | $vars = $this->post(false); |
|||||
0 ignored issues
–
show
false of type false is incompatible with the type array|string expected by parameter $name of think\Request::post() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
851 | 33 | break; |
|||||
852 | 33 | case 'PUT': |
|||||
853 | 33 | case 'DELETE': |
|||||
854 | case 'PATCH': |
||||||
855 | $vars = $this->put(false); |
||||||
0 ignored issues
–
show
false of type false is incompatible with the type array|string expected by parameter $name of think\Request::put() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
856 | break; |
||||||
857 | 33 | default: |
|||||
858 | $vars = []; |
||||||
859 | } |
||||||
860 | |||||||
861 | 33 | // 当前请求参数和URL地址中的参数合并 |
|||||
862 | $this->param = array_merge($this->param, $this->get(false), $vars, $this->route(false)); |
||||||
0 ignored issues
–
show
false of type false is incompatible with the type array|string expected by parameter $name of think\Request::get() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() false of type false is incompatible with the type array|string expected by parameter $name of think\Request::route() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
863 | 33 | ||||||
864 | $this->mergeParam = true; |
||||||
865 | } |
||||||
866 | 33 | ||||||
867 | if (is_array($name)) { |
||||||
868 | return $this->only($name, $this->param, $filter); |
||||||
869 | } |
||||||
870 | 33 | ||||||
871 | return $this->input($this->param, $name, $default, $filter); |
||||||
872 | } |
||||||
873 | |||||||
874 | /** |
||||||
875 | * 获取包含文件在内的请求参数 |
||||||
876 | * @access public |
||||||
877 | * @param string|array $name 变量名 |
||||||
878 | * @param string|array $filter 过滤方法 |
||||||
879 | * @return mixed |
||||||
880 | */ |
||||||
881 | public function all($name = '', $filter = '') |
||||||
882 | { |
||||||
883 | $data = array_merge($this->param(), $this->file() ?: []); |
||||||
0 ignored issues
–
show
It seems like
$this->file() ?: array() can also be of type think\file\UploadedFile ; however, parameter $arrays of array_merge() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() It seems like
$this->param() can also be of type null and object ; however, parameter $arrays of array_merge() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
884 | |||||||
885 | if (is_array($name)) { |
||||||
886 | $data = $this->only($name, $data, $filter); |
||||||
887 | } elseif ($name) { |
||||||
888 | $data = $data[$name] ?? null; |
||||||
889 | } |
||||||
890 | |||||||
891 | return $data; |
||||||
892 | } |
||||||
893 | |||||||
894 | /** |
||||||
895 | * 设置路由变量 |
||||||
896 | * @access public |
||||||
897 | 33 | * @param Rule $rule 路由对象 |
|||||
898 | * @return $this |
||||||
899 | 33 | */ |
|||||
900 | 33 | public function setRule(Rule $rule) |
|||||
901 | { |
||||||
902 | $this->rule = $rule; |
||||||
903 | return $this; |
||||||
904 | } |
||||||
905 | |||||||
906 | /** |
||||||
907 | * 获取当前路由对象 |
||||||
908 | 3 | * @access public |
|||||
909 | * @return Rule|null |
||||||
910 | 3 | */ |
|||||
911 | public function rule() |
||||||
912 | { |
||||||
913 | return $this->rule; |
||||||
914 | } |
||||||
915 | |||||||
916 | /** |
||||||
917 | * 设置路由变量 |
||||||
918 | * @access public |
||||||
919 | 33 | * @param array $route 路由变量 |
|||||
920 | * @return $this |
||||||
921 | 33 | */ |
|||||
922 | 33 | public function setRoute(array $route) |
|||||
923 | 33 | { |
|||||
924 | $this->route = array_merge($this->route, $route); |
||||||
925 | $this->mergeParam = false; |
||||||
926 | return $this; |
||||||
927 | } |
||||||
928 | |||||||
929 | /** |
||||||
930 | * 获取路由参数 |
||||||
931 | * @access public |
||||||
932 | * @param string|array $name 变量名 |
||||||
933 | * @param mixed $default 默认值 |
||||||
934 | 33 | * @param string|array $filter 过滤方法 |
|||||
935 | * @return mixed |
||||||
936 | 33 | */ |
|||||
937 | public function route($name = '', $default = null, $filter = '') |
||||||
938 | { |
||||||
939 | if (is_array($name)) { |
||||||
940 | 33 | return $this->only($name, $this->route, $filter); |
|||||
941 | } |
||||||
942 | |||||||
943 | return $this->input($this->route, $name, $default, $filter); |
||||||
944 | } |
||||||
945 | |||||||
946 | /** |
||||||
947 | * 获取GET参数 |
||||||
948 | * @access public |
||||||
949 | * @param string|array $name 变量名 |
||||||
950 | * @param mixed $default 默认值 |
||||||
951 | 33 | * @param string|array $filter 过滤方法 |
|||||
952 | * @return mixed |
||||||
953 | 33 | */ |
|||||
954 | public function get($name = '', $default = null, $filter = '') |
||||||
955 | { |
||||||
956 | if (is_array($name)) { |
||||||
957 | 33 | return $this->only($name, $this->get, $filter); |
|||||
958 | } |
||||||
959 | |||||||
960 | return $this->input($this->get, $name, $default, $filter); |
||||||
961 | } |
||||||
962 | |||||||
963 | /** |
||||||
964 | * 获取中间件传递的参数 |
||||||
965 | * @access public |
||||||
966 | * @param mixed $name 变量名 |
||||||
967 | * @param mixed $default 默认值 |
||||||
968 | * @return mixed |
||||||
969 | */ |
||||||
970 | public function middleware($name, $default = null) |
||||||
971 | { |
||||||
972 | return $this->middleware[$name] ?? $default; |
||||||
973 | } |
||||||
974 | |||||||
975 | /** |
||||||
976 | * 获取POST参数 |
||||||
977 | * @access public |
||||||
978 | * @param string|array $name 变量名 |
||||||
979 | * @param mixed $default 默认值 |
||||||
980 | 3 | * @param string|array $filter 过滤方法 |
|||||
981 | * @return mixed |
||||||
982 | 3 | */ |
|||||
983 | public function post($name = '', $default = null, $filter = '') |
||||||
984 | { |
||||||
985 | if (is_array($name)) { |
||||||
986 | 3 | return $this->only($name, $this->post, $filter); |
|||||
987 | } |
||||||
988 | |||||||
989 | return $this->input($this->post, $name, $default, $filter); |
||||||
990 | } |
||||||
991 | |||||||
992 | /** |
||||||
993 | * 获取PUT参数 |
||||||
994 | * @access public |
||||||
995 | * @param string|array $name 变量名 |
||||||
996 | * @param mixed $default 默认值 |
||||||
997 | * @param string|array $filter 过滤方法 |
||||||
998 | * @return mixed |
||||||
999 | */ |
||||||
1000 | public function put($name = '', $default = null, $filter = '') |
||||||
1001 | { |
||||||
1002 | if (is_array($name)) { |
||||||
1003 | return $this->only($name, $this->put, $filter); |
||||||
1004 | } |
||||||
1005 | |||||||
1006 | 30 | return $this->input($this->put, $name, $default, $filter); |
|||||
1007 | } |
||||||
1008 | 30 | ||||||
1009 | 30 | protected function getInputData($content): array |
|||||
1010 | { |
||||||
1011 | $contentType = $this->contentType(); |
||||||
1012 | 30 | if ('application/x-www-form-urlencoded' == $contentType) { |
|||||
1013 | parse_str($content, $data); |
||||||
1014 | return $data; |
||||||
1015 | } elseif (false !== strpos($contentType, 'json')) { |
||||||
1016 | 30 | return (array) json_decode($content, true); |
|||||
1017 | } |
||||||
1018 | |||||||
1019 | return []; |
||||||
1020 | } |
||||||
1021 | |||||||
1022 | /** |
||||||
1023 | * 设置获取DELETE参数 |
||||||
1024 | * @access public |
||||||
1025 | * @param mixed $name 变量名 |
||||||
1026 | * @param mixed $default 默认值 |
||||||
1027 | * @param string|array $filter 过滤方法 |
||||||
1028 | * @return mixed |
||||||
1029 | */ |
||||||
1030 | public function delete($name = '', $default = null, $filter = '') |
||||||
1031 | { |
||||||
1032 | return $this->put($name, $default, $filter); |
||||||
1033 | } |
||||||
1034 | |||||||
1035 | /** |
||||||
1036 | * 设置获取PATCH参数 |
||||||
1037 | * @access public |
||||||
1038 | * @param mixed $name 变量名 |
||||||
1039 | * @param mixed $default 默认值 |
||||||
1040 | * @param string|array $filter 过滤方法 |
||||||
1041 | * @return mixed |
||||||
1042 | */ |
||||||
1043 | public function patch($name = '', $default = null, $filter = '') |
||||||
1044 | { |
||||||
1045 | return $this->put($name, $default, $filter); |
||||||
1046 | } |
||||||
1047 | |||||||
1048 | /** |
||||||
1049 | * 获取request变量 |
||||||
1050 | * @access public |
||||||
1051 | * @param string|array $name 数据名称 |
||||||
1052 | * @param mixed $default 默认值 |
||||||
1053 | * @param string|array $filter 过滤方法 |
||||||
1054 | * @return mixed |
||||||
1055 | */ |
||||||
1056 | public function request($name = '', $default = null, $filter = '') |
||||||
1057 | { |
||||||
1058 | if (is_array($name)) { |
||||||
1059 | return $this->only($name, $this->request, $filter); |
||||||
1060 | } |
||||||
1061 | |||||||
1062 | return $this->input($this->request, $name, $default, $filter); |
||||||
1063 | } |
||||||
1064 | |||||||
1065 | /** |
||||||
1066 | * 获取环境变量 |
||||||
1067 | * @access public |
||||||
1068 | * @param string $name 数据名称 |
||||||
1069 | * @param string $default 默认值 |
||||||
1070 | * @return mixed |
||||||
1071 | */ |
||||||
1072 | public function env(string $name = '', string $default = null) |
||||||
1073 | { |
||||||
1074 | if (empty($name)) { |
||||||
1075 | return $this->env->get(); |
||||||
1076 | } else { |
||||||
1077 | $name = strtoupper($name); |
||||||
1078 | } |
||||||
1079 | |||||||
1080 | return $this->env->get($name, $default); |
||||||
1081 | } |
||||||
1082 | |||||||
1083 | /** |
||||||
1084 | * 获取session数据 |
||||||
1085 | * @access public |
||||||
1086 | * @param string $name 数据名称 |
||||||
1087 | * @param string $default 默认值 |
||||||
1088 | * @return mixed |
||||||
1089 | */ |
||||||
1090 | public function session(string $name = '', $default = null) |
||||||
1091 | { |
||||||
1092 | if ('' === $name) { |
||||||
1093 | return $this->session->all(); |
||||||
0 ignored issues
–
show
The method
all() does not exist on think\Session . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1094 | } |
||||||
1095 | return $this->session->get($name, $default); |
||||||
0 ignored issues
–
show
The method
get() does not exist on think\Session . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1096 | } |
||||||
1097 | |||||||
1098 | /** |
||||||
1099 | * 获取cookie参数 |
||||||
1100 | * @access public |
||||||
1101 | * @param mixed $name 数据名称 |
||||||
1102 | * @param string $default 默认值 |
||||||
1103 | * @param string|array $filter 过滤方法 |
||||||
1104 | * @return mixed |
||||||
1105 | */ |
||||||
1106 | public function cookie(string $name = '', $default = null, $filter = '') |
||||||
1107 | { |
||||||
1108 | if (!empty($name)) { |
||||||
1109 | $data = $this->getData($this->cookie, $name, $default); |
||||||
1110 | } else { |
||||||
1111 | $data = $this->cookie; |
||||||
1112 | } |
||||||
1113 | |||||||
1114 | // 解析过滤器 |
||||||
1115 | $filter = $this->getFilter($filter, $default); |
||||||
1116 | |||||||
1117 | if (is_array($data)) { |
||||||
1118 | array_walk_recursive($data, [$this, 'filterValue'], $filter); |
||||||
1119 | } else { |
||||||
1120 | $this->filterValue($data, $name, $filter); |
||||||
1121 | } |
||||||
1122 | |||||||
1123 | return $data; |
||||||
1124 | } |
||||||
1125 | |||||||
1126 | /** |
||||||
1127 | * 获取server参数 |
||||||
1128 | * @access public |
||||||
1129 | * @param string $name 数据名称 |
||||||
1130 | 21 | * @param string $default 默认值 |
|||||
1131 | * @return mixed |
||||||
1132 | 21 | */ |
|||||
1133 | public function server(string $name = '', string $default = '') |
||||||
1134 | { |
||||||
1135 | 21 | if (empty($name)) { |
|||||
1136 | return $this->server; |
||||||
1137 | } else { |
||||||
1138 | 21 | $name = strtoupper($name); |
|||||
1139 | } |
||||||
1140 | |||||||
1141 | return $this->server[$name] ?? $default; |
||||||
1142 | } |
||||||
1143 | |||||||
1144 | /** |
||||||
1145 | * 获取上传的文件信息 |
||||||
1146 | * @access public |
||||||
1147 | * @param string $name 名称 |
||||||
1148 | * @return null|array|UploadedFile |
||||||
1149 | */ |
||||||
1150 | public function file(string $name = '') |
||||||
1151 | { |
||||||
1152 | $files = $this->file; |
||||||
1153 | if (!empty($files)) { |
||||||
1154 | if (strpos($name, '.')) { |
||||||
1155 | [$name, $sub] = explode('.', $name); |
||||||
1156 | } |
||||||
1157 | |||||||
1158 | // 处理上传文件 |
||||||
1159 | $array = $this->dealUploadFile($files, $name); |
||||||
1160 | |||||||
1161 | if ('' === $name) { |
||||||
1162 | // 获取全部文件 |
||||||
1163 | return $array; |
||||||
1164 | } elseif (isset($sub) && isset($array[$name][$sub])) { |
||||||
1165 | return $array[$name][$sub]; |
||||||
1166 | } elseif (isset($array[$name])) { |
||||||
1167 | return $array[$name]; |
||||||
1168 | } |
||||||
1169 | } |
||||||
1170 | } |
||||||
1171 | |||||||
1172 | protected function dealUploadFile(array $files, string $name): array |
||||||
1173 | { |
||||||
1174 | $array = []; |
||||||
1175 | foreach ($files as $key => $file) { |
||||||
1176 | if (is_array($file['name'])) { |
||||||
1177 | $item = []; |
||||||
1178 | $keys = array_keys($file); |
||||||
1179 | $count = count($file['name']); |
||||||
1180 | |||||||
1181 | for ($i = 0; $i < $count; $i++) { |
||||||
1182 | if ($file['error'][$i] > 0) { |
||||||
1183 | if ($name == $key) { |
||||||
1184 | $this->throwUploadFileError($file['error'][$i]); |
||||||
1185 | } else { |
||||||
1186 | continue; |
||||||
1187 | } |
||||||
1188 | } |
||||||
1189 | |||||||
1190 | $temp['key'] = $key; |
||||||
1191 | |||||||
1192 | foreach ($keys as $_key) { |
||||||
1193 | $temp[$_key] = $file[$_key][$i]; |
||||||
1194 | } |
||||||
1195 | |||||||
1196 | $item[] = new UploadedFile($temp['tmp_name'], $temp['name'], $temp['type'], $temp['error']); |
||||||
1197 | } |
||||||
1198 | |||||||
1199 | $array[$key] = $item; |
||||||
1200 | } else { |
||||||
1201 | if ($file instanceof File) { |
||||||
1202 | $array[$key] = $file; |
||||||
1203 | } else { |
||||||
1204 | if ($file['error'] > 0) { |
||||||
1205 | if ($key == $name) { |
||||||
1206 | $this->throwUploadFileError($file['error']); |
||||||
1207 | } else { |
||||||
1208 | continue; |
||||||
1209 | } |
||||||
1210 | } |
||||||
1211 | |||||||
1212 | $array[$key] = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error']); |
||||||
1213 | } |
||||||
1214 | } |
||||||
1215 | } |
||||||
1216 | |||||||
1217 | return $array; |
||||||
1218 | } |
||||||
1219 | |||||||
1220 | protected function throwUploadFileError($error) |
||||||
1221 | { |
||||||
1222 | static $fileUploadErrors = [ |
||||||
1223 | 1 => 'upload File size exceeds the maximum value', |
||||||
1224 | 2 => 'upload File size exceeds the maximum value', |
||||||
1225 | 3 => 'only the portion of file is uploaded', |
||||||
1226 | 4 => 'no file to uploaded', |
||||||
1227 | 6 => 'upload temp dir not found', |
||||||
1228 | 7 => 'file write error', |
||||||
1229 | ]; |
||||||
1230 | |||||||
1231 | $msg = Lang::get($fileUploadErrors[$error]); |
||||||
0 ignored issues
–
show
The method
get() does not exist on think\facade\Lang . Since you implemented __callStatic , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1232 | throw new Exception($msg, $error); |
||||||
1233 | } |
||||||
1234 | |||||||
1235 | /** |
||||||
1236 | * 设置或者获取当前的Header |
||||||
1237 | * @access public |
||||||
1238 | * @param string $name header名称 |
||||||
1239 | * @param string $default 默认值 |
||||||
1240 | 30 | * @return string|array|null |
|||||
1241 | */ |
||||||
1242 | 30 | public function header(string $name = '', string $default = null) |
|||||
1243 | { |
||||||
1244 | if ('' === $name) { |
||||||
1245 | return $this->header; |
||||||
1246 | 30 | } |
|||||
1247 | |||||||
1248 | 30 | $name = str_replace('_', '-', strtolower($name)); |
|||||
1249 | |||||||
1250 | return $this->header[$name] ?? $default; |
||||||
1251 | } |
||||||
1252 | |||||||
1253 | /** |
||||||
1254 | * 获取变量 支持过滤和默认值 |
||||||
1255 | * @access public |
||||||
1256 | * @param array $data 数据源 |
||||||
1257 | * @param string|false $name 字段名 |
||||||
1258 | * @param mixed $default 默认值 |
||||||
1259 | * @param string|array $filter 过滤函数 |
||||||
1260 | 33 | * @return mixed |
|||||
1261 | */ |
||||||
1262 | 33 | public function input(array $data = [], $name = '', $default = null, $filter = '') |
|||||
1263 | { |
||||||
1264 | 33 | if (false === $name) { |
|||||
1265 | // 获取原始数据 |
||||||
1266 | return $data; |
||||||
1267 | 33 | } |
|||||
1268 | 33 | ||||||
1269 | $name = (string) $name; |
||||||
1270 | if ('' != $name) { |
||||||
1271 | // 解析name |
||||||
1272 | if (strpos($name, '/')) { |
||||||
1273 | [$name, $type] = explode('/', $name); |
||||||
1274 | } |
||||||
1275 | |||||||
1276 | $data = $this->getData($data, $name); |
||||||
1277 | |||||||
1278 | if (is_null($data)) { |
||||||
1279 | return $default; |
||||||
1280 | } |
||||||
1281 | |||||||
1282 | if (is_object($data)) { |
||||||
1283 | return $data; |
||||||
1284 | } |
||||||
1285 | 33 | } |
|||||
1286 | |||||||
1287 | 33 | $data = $this->filterData($data, $filter, $name, $default); |
|||||
1288 | |||||||
1289 | if (isset($type) && $data !== $default) { |
||||||
1290 | // 强制类型转换 |
||||||
1291 | $this->typeCast($data, $type); |
||||||
1292 | 33 | } |
|||||
1293 | |||||||
1294 | return $data; |
||||||
1295 | 33 | } |
|||||
1296 | |||||||
1297 | protected function filterData($data, $filter, $name, $default) |
||||||
1298 | 33 | { |
|||||
1299 | // 解析过滤器 |
||||||
1300 | 33 | $filter = $this->getFilter($filter, $default); |
|||||
1301 | 33 | ||||||
1302 | if (is_array($data)) { |
||||||
1303 | array_walk_recursive($data, [$this, 'filterValue'], $filter); |
||||||
1304 | } else { |
||||||
1305 | $this->filterValue($data, $name, $filter); |
||||||
1306 | 33 | } |
|||||
1307 | |||||||
1308 | return $data; |
||||||
1309 | } |
||||||
1310 | |||||||
1311 | /** |
||||||
1312 | * 强制类型转换 |
||||||
1313 | * @access protected |
||||||
1314 | * @param mixed $data |
||||||
1315 | * @param string $type |
||||||
1316 | * @return mixed |
||||||
1317 | */ |
||||||
1318 | protected function typeCast(&$data, string $type) |
||||||
1319 | { |
||||||
1320 | switch (strtolower($type)) { |
||||||
1321 | // 数组 |
||||||
1322 | case 'a': |
||||||
1323 | $data = (array) $data; |
||||||
1324 | break; |
||||||
1325 | // 数字 |
||||||
1326 | case 'd': |
||||||
1327 | $data = (int) $data; |
||||||
1328 | break; |
||||||
1329 | // 浮点 |
||||||
1330 | case 'f': |
||||||
1331 | $data = (float) $data; |
||||||
1332 | break; |
||||||
1333 | // 布尔 |
||||||
1334 | case 'b': |
||||||
1335 | $data = (boolean) $data; |
||||||
1336 | break; |
||||||
1337 | // 字符串 |
||||||
1338 | case 's': |
||||||
1339 | if (is_scalar($data)) { |
||||||
1340 | $data = (string) $data; |
||||||
1341 | } else { |
||||||
1342 | throw new \InvalidArgumentException('variable type error:' . gettype($data)); |
||||||
1343 | } |
||||||
1344 | break; |
||||||
1345 | } |
||||||
1346 | } |
||||||
1347 | |||||||
1348 | /** |
||||||
1349 | * 获取数据 |
||||||
1350 | * @access protected |
||||||
1351 | * @param array $data 数据源 |
||||||
1352 | * @param string $name 字段名 |
||||||
1353 | * @param mixed $default 默认值 |
||||||
1354 | * @return mixed |
||||||
1355 | */ |
||||||
1356 | protected function getData(array $data, string $name, $default = null) |
||||||
1357 | { |
||||||
1358 | foreach (explode('.', $name) as $val) { |
||||||
1359 | if (isset($data[$val])) { |
||||||
1360 | $data = $data[$val]; |
||||||
1361 | } else { |
||||||
1362 | return $default; |
||||||
1363 | } |
||||||
1364 | } |
||||||
1365 | |||||||
1366 | return $data; |
||||||
1367 | } |
||||||
1368 | |||||||
1369 | /** |
||||||
1370 | * 设置或获取当前的过滤规则 |
||||||
1371 | * @access public |
||||||
1372 | * @param mixed $filter 过滤规则 |
||||||
1373 | * @return mixed |
||||||
1374 | */ |
||||||
1375 | public function filter($filter = null) |
||||||
1376 | { |
||||||
1377 | if (is_null($filter)) { |
||||||
1378 | return $this->filter; |
||||||
1379 | } |
||||||
1380 | |||||||
1381 | $this->filter = $filter; |
||||||
1382 | |||||||
1383 | return $this; |
||||||
1384 | 33 | } |
|||||
1385 | |||||||
1386 | 33 | protected function getFilter($filter, $default): array |
|||||
1387 | { |
||||||
1388 | if (is_null($filter)) { |
||||||
1389 | 33 | $filter = []; |
|||||
1390 | 33 | } else { |
|||||
1391 | $filter = $filter ?: $this->filter; |
||||||
1392 | if (is_string($filter) && false === strpos($filter, '/')) { |
||||||
1393 | 33 | $filter = explode(',', $filter); |
|||||
1394 | } else { |
||||||
1395 | $filter = (array) $filter; |
||||||
1396 | } |
||||||
1397 | 33 | } |
|||||
1398 | |||||||
1399 | 33 | $filter[] = $default; |
|||||
1400 | |||||||
1401 | return $filter; |
||||||
1402 | } |
||||||
1403 | |||||||
1404 | /** |
||||||
1405 | * 递归过滤给定的值 |
||||||
1406 | * @access public |
||||||
1407 | * @param mixed $value 键值 |
||||||
1408 | * @param mixed $key 键名 |
||||||
1409 | * @param array $filters 过滤方法+默认值 |
||||||
1410 | 3 | * @return mixed |
|||||
1411 | */ |
||||||
1412 | 3 | public function filterValue(&$value, $key, $filters) |
|||||
1413 | { |
||||||
1414 | 3 | $default = array_pop($filters); |
|||||
1415 | |||||||
1416 | foreach ($filters as $filter) { |
||||||
1417 | if (is_callable($filter)) { |
||||||
1418 | // 调用函数或者方法过滤 |
||||||
1419 | if (is_null($value)) { |
||||||
1420 | continue; |
||||||
1421 | } |
||||||
1422 | |||||||
1423 | $value = call_user_func($filter, $value); |
||||||
1424 | } elseif (is_scalar($value)) { |
||||||
1425 | if (is_string($filter) && false !== strpos($filter, '/')) { |
||||||
1426 | // 正则过滤 |
||||||
1427 | if (!preg_match($filter, $value)) { |
||||||
1428 | // 匹配不成功返回默认值 |
||||||
1429 | $value = $default; |
||||||
1430 | break; |
||||||
1431 | } |
||||||
1432 | } elseif (!empty($filter)) { |
||||||
1433 | // filter函数不存在时, 则使用filter_var进行过滤 |
||||||
1434 | // filter为非整形值时, 调用filter_id取得过滤id |
||||||
1435 | $value = filter_var($value, is_int($filter) ? $filter : filter_id($filter)); |
||||||
1436 | if (false === $value) { |
||||||
1437 | $value = $default; |
||||||
1438 | 3 | break; |
|||||
1439 | } |
||||||
1440 | } |
||||||
1441 | } |
||||||
1442 | } |
||||||
1443 | |||||||
1444 | return $value; |
||||||
1445 | } |
||||||
1446 | |||||||
1447 | /** |
||||||
1448 | * 是否存在某个请求参数 |
||||||
1449 | * @access public |
||||||
1450 | * @param string $name 变量名 |
||||||
1451 | * @param string $type 变量类型 |
||||||
1452 | * @param bool $checkEmpty 是否检测空值 |
||||||
1453 | * @return bool |
||||||
1454 | */ |
||||||
1455 | public function has(string $name, string $type = 'param', bool $checkEmpty = false): bool |
||||||
1456 | { |
||||||
1457 | if (!in_array($type, ['param', 'get', 'post', 'put', 'patch', 'route', 'delete', 'cookie', 'session', 'env', 'request', 'server', 'header', 'file'])) { |
||||||
1458 | return false; |
||||||
1459 | } |
||||||
1460 | |||||||
1461 | $param = empty($this->$type) ? $this->$type() : $this->$type; |
||||||
1462 | |||||||
1463 | if (is_object($param)) { |
||||||
1464 | return $param->has($name); |
||||||
1465 | } |
||||||
1466 | |||||||
1467 | // 按.拆分成多维数组进行判断 |
||||||
1468 | foreach (explode('.', $name) as $val) { |
||||||
1469 | if (isset($param[$val])) { |
||||||
1470 | $param = $param[$val]; |
||||||
1471 | } else { |
||||||
1472 | return false; |
||||||
1473 | } |
||||||
1474 | } |
||||||
1475 | |||||||
1476 | return ($checkEmpty && '' === $param) ? false : true; |
||||||
1477 | } |
||||||
1478 | |||||||
1479 | /** |
||||||
1480 | * 获取指定的参数 |
||||||
1481 | * @access public |
||||||
1482 | * @param array $name 变量名 |
||||||
1483 | * @param mixed $data 数据或者变量类型 |
||||||
1484 | * @param string|array $filter 过滤方法 |
||||||
1485 | * @return array |
||||||
1486 | */ |
||||||
1487 | public function only(array $name, $data = 'param', $filter = ''): array |
||||||
1488 | { |
||||||
1489 | $data = is_array($data) ? $data : $this->$data(); |
||||||
1490 | |||||||
1491 | $item = []; |
||||||
1492 | foreach ($name as $key => $val) { |
||||||
1493 | |||||||
1494 | if (is_int($key)) { |
||||||
1495 | $default = null; |
||||||
1496 | $key = $val; |
||||||
1497 | if (!key_exists($key, $data)) { |
||||||
1498 | continue; |
||||||
1499 | } |
||||||
1500 | } else { |
||||||
1501 | $default = $val; |
||||||
1502 | } |
||||||
1503 | |||||||
1504 | $item[$key] = $this->filterData($data[$key] ?? $default, $filter, $key, $default); |
||||||
1505 | } |
||||||
1506 | |||||||
1507 | return $item; |
||||||
1508 | } |
||||||
1509 | |||||||
1510 | /** |
||||||
1511 | * 排除指定参数获取 |
||||||
1512 | * @access public |
||||||
1513 | * @param array $name 变量名 |
||||||
1514 | * @param string $type 变量类型 |
||||||
1515 | * @return mixed |
||||||
1516 | */ |
||||||
1517 | public function except(array $name, string $type = 'param'): array |
||||||
1518 | { |
||||||
1519 | $param = $this->$type(); |
||||||
1520 | |||||||
1521 | foreach ($name as $key) { |
||||||
1522 | if (isset($param[$key])) { |
||||||
1523 | unset($param[$key]); |
||||||
1524 | } |
||||||
1525 | } |
||||||
1526 | |||||||
1527 | return $param; |
||||||
1528 | } |
||||||
1529 | |||||||
1530 | /** |
||||||
1531 | * 当前是否ssl |
||||||
1532 | * @access public |
||||||
1533 | * @return bool |
||||||
1534 | */ |
||||||
1535 | public function isSsl(): bool |
||||||
1536 | { |
||||||
1537 | if ($this->server('HTTPS') && ('1' == $this->server('HTTPS') || 'on' == strtolower($this->server('HTTPS')))) { |
||||||
1538 | return true; |
||||||
1539 | } elseif ('https' == $this->server('REQUEST_SCHEME')) { |
||||||
1540 | return true; |
||||||
1541 | } elseif ('443' == $this->server('SERVER_PORT')) { |
||||||
1542 | return true; |
||||||
1543 | } elseif ('https' == $this->server('HTTP_X_FORWARDED_PROTO')) { |
||||||
1544 | return true; |
||||||
1545 | } elseif ($this->httpsAgentName && $this->server($this->httpsAgentName)) { |
||||||
1546 | return true; |
||||||
1547 | } |
||||||
1548 | |||||||
1549 | return false; |
||||||
1550 | } |
||||||
1551 | 21 | ||||||
1552 | /** |
||||||
1553 | 21 | * 当前是否JSON请求 |
|||||
1554 | * @access public |
||||||
1555 | 21 | * @return bool |
|||||
1556 | */ |
||||||
1557 | public function isJson(): bool |
||||||
1558 | { |
||||||
1559 | $acceptType = $this->type(); |
||||||
1560 | |||||||
1561 | return false !== strpos($acceptType, 'json'); |
||||||
1562 | } |
||||||
1563 | |||||||
1564 | /** |
||||||
1565 | * 当前是否Ajax请求 |
||||||
1566 | * @access public |
||||||
1567 | * @param bool $ajax true 获取原始ajax请求 |
||||||
1568 | * @return bool |
||||||
1569 | */ |
||||||
1570 | public function isAjax(bool $ajax = false): bool |
||||||
1571 | { |
||||||
1572 | $value = $this->server('HTTP_X_REQUESTED_WITH'); |
||||||
1573 | $result = $value && 'xmlhttprequest' == strtolower($value) ? true : false; |
||||||
1574 | |||||||
1575 | if (true === $ajax) { |
||||||
1576 | return $result; |
||||||
1577 | } |
||||||
1578 | |||||||
1579 | return $this->param($this->varAjax) ? true : $result; |
||||||
1580 | } |
||||||
1581 | |||||||
1582 | /** |
||||||
1583 | * 当前是否Pjax请求 |
||||||
1584 | * @access public |
||||||
1585 | * @param bool $pjax true 获取原始pjax请求 |
||||||
1586 | * @return bool |
||||||
1587 | */ |
||||||
1588 | public function isPjax(bool $pjax = false): bool |
||||||
1589 | { |
||||||
1590 | $result = !empty($this->server('HTTP_X_PJAX')) ? true : false; |
||||||
1591 | |||||||
1592 | if (true === $pjax) { |
||||||
1593 | return $result; |
||||||
1594 | } |
||||||
1595 | |||||||
1596 | return $this->param($this->varPjax) ? true : $result; |
||||||
1597 | } |
||||||
1598 | |||||||
1599 | /** |
||||||
1600 | * 获取客户端IP地址 |
||||||
1601 | * @access public |
||||||
1602 | * @return string |
||||||
1603 | */ |
||||||
1604 | public function ip(): string |
||||||
1605 | { |
||||||
1606 | if (!empty($this->realIP)) { |
||||||
1607 | return $this->realIP; |
||||||
1608 | } |
||||||
1609 | |||||||
1610 | $this->realIP = $this->server('REMOTE_ADDR', ''); |
||||||
1611 | |||||||
1612 | // 如果指定了前端代理服务器IP以及其会发送的IP头 |
||||||
1613 | // 则尝试获取前端代理服务器发送过来的真实IP |
||||||
1614 | $proxyIp = $this->proxyServerIp; |
||||||
1615 | $proxyIpHeader = $this->proxyServerIpHeader; |
||||||
1616 | |||||||
1617 | if (count($proxyIp) > 0 && count($proxyIpHeader) > 0) { |
||||||
1618 | // 从指定的HTTP头中依次尝试获取IP地址 |
||||||
1619 | // 直到获取到一个合法的IP地址 |
||||||
1620 | foreach ($proxyIpHeader as $header) { |
||||||
1621 | $tempIP = $this->server($header); |
||||||
1622 | |||||||
1623 | if (empty($tempIP)) { |
||||||
1624 | continue; |
||||||
1625 | } |
||||||
1626 | |||||||
1627 | $tempIP = trim(explode(',', $tempIP)[0]); |
||||||
0 ignored issues
–
show
It seems like
$tempIP can also be of type array ; however, parameter $string of explode() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1628 | |||||||
1629 | if (!$this->isValidIP($tempIP)) { |
||||||
1630 | $tempIP = null; |
||||||
1631 | } else { |
||||||
1632 | break; |
||||||
1633 | } |
||||||
1634 | } |
||||||
1635 | |||||||
1636 | // tempIP不为空,说明获取到了一个IP地址 |
||||||
1637 | // 这时我们检查 REMOTE_ADDR 是不是指定的前端代理服务器之一 |
||||||
1638 | // 如果是的话说明该 IP头 是由前端代理服务器设置的 |
||||||
1639 | // 否则则是伪装的 |
||||||
1640 | if (!empty($tempIP)) { |
||||||
1641 | $realIPBin = $this->ip2bin($this->realIP); |
||||||
1642 | |||||||
1643 | foreach ($proxyIp as $ip) { |
||||||
1644 | $serverIPElements = explode('/', $ip); |
||||||
1645 | $serverIP = $serverIPElements[0]; |
||||||
1646 | $serverIPPrefix = $serverIPElements[1] ?? 128; |
||||||
1647 | $serverIPBin = $this->ip2bin($serverIP); |
||||||
1648 | |||||||
1649 | // IP类型不符 |
||||||
1650 | if (strlen($realIPBin) !== strlen($serverIPBin)) { |
||||||
1651 | continue; |
||||||
1652 | } |
||||||
1653 | |||||||
1654 | if (strncmp($realIPBin, $serverIPBin, (int) $serverIPPrefix) === 0) { |
||||||
1655 | $this->realIP = $tempIP; |
||||||
1656 | break; |
||||||
1657 | } |
||||||
1658 | } |
||||||
1659 | } |
||||||
1660 | } |
||||||
1661 | |||||||
1662 | if (!$this->isValidIP($this->realIP)) { |
||||||
1663 | $this->realIP = '0.0.0.0'; |
||||||
1664 | } |
||||||
1665 | |||||||
1666 | return $this->realIP; |
||||||
1667 | } |
||||||
1668 | |||||||
1669 | /** |
||||||
1670 | * 检测是否是合法的IP地址 |
||||||
1671 | * |
||||||
1672 | * @param string $ip IP地址 |
||||||
1673 | * @param string $type IP地址类型 (ipv4, ipv6) |
||||||
1674 | * |
||||||
1675 | * @return boolean |
||||||
1676 | */ |
||||||
1677 | public function isValidIP(string $ip, string $type = ''): bool |
||||||
1678 | { |
||||||
1679 | switch (strtolower($type)) { |
||||||
1680 | case 'ipv4': |
||||||
1681 | $flag = FILTER_FLAG_IPV4; |
||||||
1682 | break; |
||||||
1683 | case 'ipv6': |
||||||
1684 | $flag = FILTER_FLAG_IPV6; |
||||||
1685 | break; |
||||||
1686 | default: |
||||||
1687 | $flag = 0; |
||||||
1688 | break; |
||||||
1689 | } |
||||||
1690 | |||||||
1691 | return boolval(filter_var($ip, FILTER_VALIDATE_IP, $flag)); |
||||||
1692 | } |
||||||
1693 | |||||||
1694 | /** |
||||||
1695 | * 将IP地址转换为二进制字符串 |
||||||
1696 | * |
||||||
1697 | * @param string $ip |
||||||
1698 | * |
||||||
1699 | * @return string |
||||||
1700 | */ |
||||||
1701 | public function ip2bin(string $ip): string |
||||||
1702 | { |
||||||
1703 | if ($this->isValidIP($ip, 'ipv6')) { |
||||||
1704 | $IPHex = str_split(bin2hex(inet_pton($ip)), 4); |
||||||
1705 | foreach ($IPHex as $key => $value) { |
||||||
1706 | $IPHex[$key] = intval($value, 16); |
||||||
1707 | } |
||||||
1708 | $IPBin = vsprintf('%016b%016b%016b%016b%016b%016b%016b%016b', $IPHex); |
||||||
0 ignored issues
–
show
It seems like
$IPHex can also be of type true ; however, parameter $values of vsprintf() does only seem to accept array , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1709 | } else { |
||||||
1710 | $IPHex = str_split(bin2hex(inet_pton($ip)), 2); |
||||||
1711 | foreach ($IPHex as $key => $value) { |
||||||
1712 | $IPHex[$key] = intval($value, 16); |
||||||
1713 | } |
||||||
1714 | $IPBin = vsprintf('%08b%08b%08b%08b', $IPHex); |
||||||
1715 | } |
||||||
1716 | |||||||
1717 | return $IPBin; |
||||||
1718 | } |
||||||
1719 | |||||||
1720 | /** |
||||||
1721 | * 检测是否使用手机访问 |
||||||
1722 | * @access public |
||||||
1723 | * @return bool |
||||||
1724 | */ |
||||||
1725 | public function isMobile(): bool |
||||||
1726 | { |
||||||
1727 | if ($this->server('HTTP_VIA') && stristr($this->server('HTTP_VIA'), "wap")) { |
||||||
1728 | return true; |
||||||
1729 | } elseif ($this->server('HTTP_ACCEPT') && strpos(strtoupper($this->server('HTTP_ACCEPT')), "VND.WAP.WML")) { |
||||||
1730 | return true; |
||||||
1731 | } elseif ($this->server('HTTP_X_WAP_PROFILE') || $this->server('HTTP_PROFILE')) { |
||||||
1732 | return true; |
||||||
1733 | } elseif ($this->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', $this->server('HTTP_USER_AGENT'))) { |
||||||
1734 | return true; |
||||||
1735 | } |
||||||
1736 | |||||||
1737 | return false; |
||||||
1738 | } |
||||||
1739 | |||||||
1740 | /** |
||||||
1741 | * 当前URL地址中的scheme参数 |
||||||
1742 | * @access public |
||||||
1743 | * @return string |
||||||
1744 | */ |
||||||
1745 | public function scheme(): string |
||||||
1746 | { |
||||||
1747 | return $this->isSsl() ? 'https' : 'http'; |
||||||
1748 | } |
||||||
1749 | |||||||
1750 | /** |
||||||
1751 | * 当前请求URL地址中的query参数 |
||||||
1752 | * @access public |
||||||
1753 | * @return string |
||||||
1754 | */ |
||||||
1755 | public function query(): string |
||||||
1756 | { |
||||||
1757 | return $this->server('QUERY_STRING', ''); |
||||||
1758 | } |
||||||
1759 | |||||||
1760 | /** |
||||||
1761 | * 设置当前请求的host(包含端口) |
||||||
1762 | * @access public |
||||||
1763 | * @param string $host 主机名(含端口) |
||||||
1764 | * @return $this |
||||||
1765 | */ |
||||||
1766 | public function setHost(string $host) |
||||||
1767 | { |
||||||
1768 | $this->host = $host; |
||||||
1769 | |||||||
1770 | return $this; |
||||||
1771 | } |
||||||
1772 | |||||||
1773 | /** |
||||||
1774 | * 当前请求的host |
||||||
1775 | * @access public |
||||||
1776 | * @param bool $strict true 仅仅获取HOST |
||||||
1777 | * @return string |
||||||
1778 | */ |
||||||
1779 | public function host(bool $strict = false): string |
||||||
1780 | { |
||||||
1781 | if ($this->host) { |
||||||
1782 | $host = $this->host; |
||||||
1783 | } else { |
||||||
1784 | $host = strval($this->server('HTTP_X_FORWARDED_HOST') ?: $this->server('HTTP_HOST')); |
||||||
1785 | } |
||||||
1786 | |||||||
1787 | return true === $strict && strpos($host, ':') ? strstr($host, ':', true) : $host; |
||||||
1788 | } |
||||||
1789 | |||||||
1790 | /** |
||||||
1791 | * 当前请求URL地址中的port参数 |
||||||
1792 | * @access public |
||||||
1793 | * @return int |
||||||
1794 | */ |
||||||
1795 | public function port(): int |
||||||
1796 | { |
||||||
1797 | return (int) ($this->server('HTTP_X_FORWARDED_PORT') ?: $this->server('SERVER_PORT', '')); |
||||||
1798 | } |
||||||
1799 | |||||||
1800 | /** |
||||||
1801 | * 当前请求 SERVER_PROTOCOL |
||||||
1802 | * @access public |
||||||
1803 | * @return string |
||||||
1804 | */ |
||||||
1805 | public function protocol(): string |
||||||
1806 | { |
||||||
1807 | return $this->server('SERVER_PROTOCOL', ''); |
||||||
1808 | } |
||||||
1809 | |||||||
1810 | /** |
||||||
1811 | * 当前请求 REMOTE_PORT |
||||||
1812 | * @access public |
||||||
1813 | * @return int |
||||||
1814 | */ |
||||||
1815 | public function remotePort(): int |
||||||
1816 | { |
||||||
1817 | return (int) $this->server('REMOTE_PORT', ''); |
||||||
1818 | } |
||||||
1819 | 30 | ||||||
1820 | /** |
||||||
1821 | 30 | * 当前请求 HTTP_CONTENT_TYPE |
|||||
1822 | * @access public |
||||||
1823 | 30 | * @return string |
|||||
1824 | */ |
||||||
1825 | public function contentType(): string |
||||||
1826 | { |
||||||
1827 | $contentType = $this->header('Content-Type'); |
||||||
1828 | |||||||
1829 | if ($contentType) { |
||||||
1830 | if (strpos($contentType, ';')) { |
||||||
0 ignored issues
–
show
It seems like
$contentType can also be of type array ; however, parameter $haystack of strpos() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1831 | [$type] = explode(';', $contentType); |
||||||
0 ignored issues
–
show
It seems like
$contentType can also be of type array ; however, parameter $string of explode() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1832 | 30 | } else { |
|||||
1833 | $type = $contentType; |
||||||
1834 | } |
||||||
1835 | return trim($type); |
||||||
0 ignored issues
–
show
It seems like
$type can also be of type array ; however, parameter $string of trim() does only seem to accept string , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1836 | } |
||||||
1837 | |||||||
1838 | return ''; |
||||||
1839 | } |
||||||
1840 | |||||||
1841 | /** |
||||||
1842 | * 获取当前请求的安全Key |
||||||
1843 | * @access public |
||||||
1844 | * @return string |
||||||
1845 | */ |
||||||
1846 | public function secureKey(): string |
||||||
1847 | { |
||||||
1848 | if (is_null($this->secureKey)) { |
||||||
0 ignored issues
–
show
|
|||||||
1849 | $this->secureKey = uniqid('', true); |
||||||
1850 | } |
||||||
1851 | |||||||
1852 | return $this->secureKey; |
||||||
1853 | } |
||||||
1854 | |||||||
1855 | 15 | /** |
|||||
1856 | * 设置当前的控制器名 |
||||||
1857 | 15 | * @access public |
|||||
1858 | 15 | * @param string $controller 控制器名 |
|||||
1859 | * @return $this |
||||||
1860 | */ |
||||||
1861 | public function setController(string $controller) |
||||||
1862 | { |
||||||
1863 | $this->controller = $controller; |
||||||
1864 | return $this; |
||||||
1865 | } |
||||||
1866 | |||||||
1867 | 15 | /** |
|||||
1868 | * 设置当前的操作名 |
||||||
1869 | 15 | * @access public |
|||||
1870 | 15 | * @param string $action 操作名 |
|||||
1871 | * @return $this |
||||||
1872 | */ |
||||||
1873 | public function setAction(string $action) |
||||||
1874 | { |
||||||
1875 | $this->action = $action; |
||||||
1876 | return $this; |
||||||
1877 | } |
||||||
1878 | |||||||
1879 | /** |
||||||
1880 | * 获取当前的控制器名 |
||||||
1881 | * @access public |
||||||
1882 | * @param bool $convert 转换为小写 |
||||||
1883 | * @return string |
||||||
1884 | */ |
||||||
1885 | public function controller(bool $convert = false): string |
||||||
1886 | { |
||||||
1887 | $name = $this->controller ?: ''; |
||||||
1888 | return $convert ? strtolower($name) : $name; |
||||||
1889 | } |
||||||
1890 | |||||||
1891 | 3 | /** |
|||||
1892 | * 获取当前的操作名 |
||||||
1893 | 3 | * @access public |
|||||
1894 | 3 | * @param bool $convert 转换为小写 |
|||||
1895 | * @return string |
||||||
1896 | */ |
||||||
1897 | public function action(bool $convert = false): string |
||||||
1898 | { |
||||||
1899 | $name = $this->action ?: ''; |
||||||
1900 | return $convert ? strtolower($name) : $name; |
||||||
1901 | } |
||||||
1902 | |||||||
1903 | /** |
||||||
1904 | * 设置或者获取当前请求的content |
||||||
1905 | * @access public |
||||||
1906 | * @return string |
||||||
1907 | */ |
||||||
1908 | public function getContent(): string |
||||||
1909 | { |
||||||
1910 | if (is_null($this->content)) { |
||||||
0 ignored issues
–
show
|
|||||||
1911 | $this->content = $this->input; |
||||||
1912 | } |
||||||
1913 | |||||||
1914 | return $this->content; |
||||||
1915 | } |
||||||
1916 | |||||||
1917 | /** |
||||||
1918 | * 获取当前请求的php://input |
||||||
1919 | * @access public |
||||||
1920 | * @return string |
||||||
1921 | */ |
||||||
1922 | public function getInput(): string |
||||||
1923 | { |
||||||
1924 | return $this->input; |
||||||
1925 | } |
||||||
1926 | |||||||
1927 | /** |
||||||
1928 | * 生成请求令牌 |
||||||
1929 | * @access public |
||||||
1930 | * @param string $name 令牌名称 |
||||||
1931 | * @param mixed $type 令牌生成方法 |
||||||
1932 | * @return string |
||||||
1933 | */ |
||||||
1934 | public function buildToken(string $name = '__token__', $type = 'md5'): string |
||||||
1935 | { |
||||||
1936 | $type = is_callable($type) ? $type : 'md5'; |
||||||
1937 | $token = call_user_func($type, $this->server('REQUEST_TIME_FLOAT')); |
||||||
1938 | |||||||
1939 | $this->session->set($name, $token); |
||||||
0 ignored issues
–
show
The method
set() does not exist on think\Session . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1940 | |||||||
1941 | return $token; |
||||||
1942 | } |
||||||
1943 | |||||||
1944 | /** |
||||||
1945 | * 检查请求令牌 |
||||||
1946 | * @access public |
||||||
1947 | * @param string $token 令牌名称 |
||||||
1948 | * @param array $data 表单数据 |
||||||
1949 | * @return bool |
||||||
1950 | */ |
||||||
1951 | public function checkToken(string $token = '__token__', array $data = []): bool |
||||||
1952 | { |
||||||
1953 | if (in_array($this->method(), ['GET', 'HEAD', 'OPTIONS'], true)) { |
||||||
1954 | return true; |
||||||
1955 | } |
||||||
1956 | |||||||
1957 | if (!$this->session->has($token)) { |
||||||
0 ignored issues
–
show
The method
has() does not exist on think\Session . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1958 | // 令牌数据无效 |
||||||
1959 | return false; |
||||||
1960 | } |
||||||
1961 | |||||||
1962 | // Header验证 |
||||||
1963 | if ($this->header('X-CSRF-TOKEN') && $this->session->get($token) === $this->header('X-CSRF-TOKEN')) { |
||||||
1964 | // 防止重复提交 |
||||||
1965 | $this->session->delete($token); // 验证完成销毁session |
||||||
0 ignored issues
–
show
The method
delete() does not exist on think\Session . Since you implemented __call , consider adding a @method annotation.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||||
1966 | return true; |
||||||
1967 | } |
||||||
1968 | |||||||
1969 | if (empty($data)) { |
||||||
1970 | $data = $this->post(); |
||||||
1971 | } |
||||||
1972 | |||||||
1973 | // 令牌验证 |
||||||
1974 | if (isset($data[$token]) && $this->session->get($token) === $data[$token]) { |
||||||
1975 | // 防止重复提交 |
||||||
1976 | $this->session->delete($token); // 验证完成销毁session |
||||||
1977 | return true; |
||||||
1978 | } |
||||||
1979 | |||||||
1980 | // 开启TOKEN重置 |
||||||
1981 | $this->session->delete($token); |
||||||
1982 | return false; |
||||||
1983 | } |
||||||
1984 | |||||||
1985 | /** |
||||||
1986 | * 设置在中间件传递的数据 |
||||||
1987 | * @access public |
||||||
1988 | * @param array $middleware 数据 |
||||||
1989 | * @return $this |
||||||
1990 | */ |
||||||
1991 | public function withMiddleware(array $middleware) |
||||||
1992 | { |
||||||
1993 | $this->middleware = array_merge($this->middleware, $middleware); |
||||||
1994 | return $this; |
||||||
1995 | } |
||||||
1996 | |||||||
1997 | /** |
||||||
1998 | * 设置GET数据 |
||||||
1999 | * @access public |
||||||
2000 | * @param array $get 数据 |
||||||
2001 | * @return $this |
||||||
2002 | */ |
||||||
2003 | public function withGet(array $get) |
||||||
2004 | { |
||||||
2005 | $this->get = $get; |
||||||
2006 | return $this; |
||||||
2007 | } |
||||||
2008 | |||||||
2009 | /** |
||||||
2010 | * 设置POST数据 |
||||||
2011 | * @access public |
||||||
2012 | * @param array $post 数据 |
||||||
2013 | * @return $this |
||||||
2014 | */ |
||||||
2015 | public function withPost(array $post) |
||||||
2016 | { |
||||||
2017 | $this->post = $post; |
||||||
2018 | return $this; |
||||||
2019 | } |
||||||
2020 | |||||||
2021 | /** |
||||||
2022 | * 设置COOKIE数据 |
||||||
2023 | * @access public |
||||||
2024 | * @param array $cookie 数据 |
||||||
2025 | * @return $this |
||||||
2026 | */ |
||||||
2027 | public function withCookie(array $cookie) |
||||||
2028 | { |
||||||
2029 | $this->cookie = $cookie; |
||||||
2030 | return $this; |
||||||
2031 | } |
||||||
2032 | |||||||
2033 | /** |
||||||
2034 | * 设置SESSION数据 |
||||||
2035 | * @access public |
||||||
2036 | * @param Session $session 数据 |
||||||
2037 | * @return $this |
||||||
2038 | */ |
||||||
2039 | public function withSession(Session $session) |
||||||
2040 | { |
||||||
2041 | $this->session = $session; |
||||||
2042 | return $this; |
||||||
2043 | } |
||||||
2044 | |||||||
2045 | /** |
||||||
2046 | * 设置SERVER数据 |
||||||
2047 | * @access public |
||||||
2048 | * @param array $server 数据 |
||||||
2049 | * @return $this |
||||||
2050 | */ |
||||||
2051 | public function withServer(array $server) |
||||||
2052 | { |
||||||
2053 | $this->server = array_change_key_case($server, CASE_UPPER); |
||||||
2054 | return $this; |
||||||
2055 | } |
||||||
2056 | |||||||
2057 | /** |
||||||
2058 | * 设置HEADER数据 |
||||||
2059 | * @access public |
||||||
2060 | * @param array $header 数据 |
||||||
2061 | * @return $this |
||||||
2062 | */ |
||||||
2063 | public function withHeader(array $header) |
||||||
2064 | { |
||||||
2065 | $this->header = array_change_key_case($header); |
||||||
2066 | return $this; |
||||||
2067 | } |
||||||
2068 | |||||||
2069 | /** |
||||||
2070 | * 设置ENV数据 |
||||||
2071 | * @access public |
||||||
2072 | * @param Env $env 数据 |
||||||
2073 | * @return $this |
||||||
2074 | */ |
||||||
2075 | public function withEnv(Env $env) |
||||||
2076 | { |
||||||
2077 | $this->env = $env; |
||||||
2078 | return $this; |
||||||
2079 | } |
||||||
2080 | |||||||
2081 | /** |
||||||
2082 | * 设置php://input数据 |
||||||
2083 | * @access public |
||||||
2084 | * @param string $input RAW数据 |
||||||
2085 | * @return $this |
||||||
2086 | */ |
||||||
2087 | public function withInput(string $input) |
||||||
2088 | { |
||||||
2089 | $this->input = $input; |
||||||
2090 | if (!empty($input)) { |
||||||
2091 | $inputData = $this->getInputData($input); |
||||||
2092 | if (!empty($inputData)) { |
||||||
2093 | $this->post = $inputData; |
||||||
2094 | $this->put = $inputData; |
||||||
2095 | } |
||||||
2096 | } |
||||||
2097 | return $this; |
||||||
2098 | } |
||||||
2099 | |||||||
2100 | /** |
||||||
2101 | * 设置文件上传数据 |
||||||
2102 | * @access public |
||||||
2103 | * @param array $files 上传信息 |
||||||
2104 | * @return $this |
||||||
2105 | */ |
||||||
2106 | public function withFiles(array $files) |
||||||
2107 | { |
||||||
2108 | $this->file = $files; |
||||||
2109 | return $this; |
||||||
2110 | } |
||||||
2111 | |||||||
2112 | /** |
||||||
2113 | * 设置ROUTE变量 |
||||||
2114 | * @access public |
||||||
2115 | * @param array $route 数据 |
||||||
2116 | * @return $this |
||||||
2117 | */ |
||||||
2118 | public function withRoute(array $route) |
||||||
2119 | { |
||||||
2120 | $this->route = $route; |
||||||
2121 | return $this; |
||||||
2122 | } |
||||||
2123 | |||||||
2124 | /** |
||||||
2125 | * 设置中间传递数据 |
||||||
2126 | * @access public |
||||||
2127 | * @param string $name 参数名 |
||||||
2128 | * @param mixed $value 值 |
||||||
2129 | */ |
||||||
2130 | public function __set(string $name, $value) |
||||||
2131 | { |
||||||
2132 | $this->middleware[$name] = $value; |
||||||
2133 | } |
||||||
2134 | |||||||
2135 | /** |
||||||
2136 | * 获取中间传递数据的值 |
||||||
2137 | * @access public |
||||||
2138 | * @param string $name 名称 |
||||||
2139 | * @return mixed |
||||||
2140 | */ |
||||||
2141 | public function __get(string $name) |
||||||
2142 | { |
||||||
2143 | return $this->middleware($name); |
||||||
2144 | } |
||||||
2145 | |||||||
2146 | /** |
||||||
2147 | * 检测中间传递数据的值 |
||||||
2148 | * @access public |
||||||
2149 | * @param string $name 名称 |
||||||
2150 | * @return boolean |
||||||
2151 | */ |
||||||
2152 | public function __isset(string $name): bool |
||||||
2153 | { |
||||||
2154 | return isset($this->middleware[$name]); |
||||||
2155 | } |
||||||
2156 | |||||||
2157 | // ArrayAccess |
||||||
2158 | #[\ReturnTypeWillChange] |
||||||
2159 | public function offsetExists($name): bool |
||||||
2160 | { |
||||||
2161 | return $this->has($name); |
||||||
2162 | } |
||||||
2163 | |||||||
2164 | #[\ReturnTypeWillChange] |
||||||
2165 | public function offsetGet($name) |
||||||
2166 | { |
||||||
2167 | return $this->param($name); |
||||||
2168 | } |
||||||
2169 | |||||||
2170 | #[\ReturnTypeWillChange] |
||||||
2171 | public function offsetSet($name, $value) |
||||||
2172 | {} |
||||||
2173 | |||||||
2174 | #[\ReturnTypeWillChange] |
||||||
2175 | public function offsetUnset($name) |
||||||
2176 | {} |
||||||
2177 | |||||||
2178 | } |
||||||
2179 |
Let?s assume that you have a directory layout like this:
and let?s assume the following content of
Bar.php
:If both files
OtherDir/Foo.php
andSomeDir/Foo.php
are loaded in the same runtime, you will see a PHP error such as the following:PHP Fatal error: Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php
However, as
OtherDir/Foo.php
does not necessarily have to be loaded and the error is only triggered if it is loaded beforeOtherDir/Bar.php
, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias: