445 lines
9.4 KiB
PHP
445 lines
9.4 KiB
PHP
<?php
|
||
|
||
namespace top\library\http;
|
||
|
||
use top\middleware\ifs\MiddlewareIfs;
|
||
use top\middleware\Init;
|
||
use top\library\Register;
|
||
use top\library\route\driver\Command;
|
||
use top\library\route\driver\Pathinfo;
|
||
use top\library\Router;
|
||
use top\middleware\View;
|
||
use top\traits\Instance;
|
||
|
||
/**
|
||
* 请求类
|
||
* @author topnuomi 2018年11月23日
|
||
*/
|
||
class Request
|
||
{
|
||
|
||
use Instance;
|
||
|
||
/**
|
||
* 保存$_SERVER变量
|
||
* @var array
|
||
*/
|
||
private $server = [];
|
||
|
||
/**
|
||
* 中间件
|
||
* @var array
|
||
*/
|
||
private $middleware = [];
|
||
|
||
/**
|
||
* 路由实例
|
||
* @var null
|
||
*/
|
||
private $router = null;
|
||
|
||
/**
|
||
* 模块名
|
||
* @var string
|
||
*/
|
||
private $module = '';
|
||
|
||
/**
|
||
* 控制器完整类名
|
||
* @var string
|
||
*/
|
||
private $class = '';
|
||
|
||
/**
|
||
* 控制器名
|
||
* @var string
|
||
*/
|
||
private $ctrl = '';
|
||
|
||
/**
|
||
* 请求参数
|
||
* @var array
|
||
*/
|
||
private $params = [];
|
||
|
||
/**
|
||
* post、get数据删除的值
|
||
* @var array
|
||
*/
|
||
private $except = [];
|
||
|
||
private function __construct()
|
||
{
|
||
$this->server = (!empty($_SERVER)) ? $_SERVER : [];
|
||
}
|
||
|
||
/**
|
||
* 当前请求方式
|
||
* @return mixed|string
|
||
*/
|
||
private function requestMethod()
|
||
{
|
||
return (isset($this->server['REQUEST_METHOD']) && $this->server['REQUEST_METHOD'] != '') ? $this->server['REQUEST_METHOD'] : '';
|
||
}
|
||
|
||
/**
|
||
* POST
|
||
* @return boolean
|
||
*/
|
||
public function isPost()
|
||
{
|
||
return $this->requestMethod() == 'POST';
|
||
}
|
||
|
||
/**
|
||
* GET
|
||
* @return boolean
|
||
*/
|
||
public function isGet()
|
||
{
|
||
return $this->requestMethod() == 'GET';
|
||
}
|
||
|
||
/**
|
||
* PUT
|
||
* @return boolean
|
||
*/
|
||
public function isPut()
|
||
{
|
||
return $this->requestMethod() == 'PUT';
|
||
}
|
||
|
||
/**
|
||
* DELETE
|
||
* @return boolean
|
||
*/
|
||
public function isDelete()
|
||
{
|
||
return $this->requestMethod() == 'DELETE';
|
||
}
|
||
|
||
/**
|
||
* HEAD
|
||
* @return boolean
|
||
*/
|
||
public function isHead()
|
||
{
|
||
return $this->requestMethod() == 'HEAD';
|
||
}
|
||
|
||
/**
|
||
* HEAD
|
||
* @return boolean
|
||
*/
|
||
public function isPatch()
|
||
{
|
||
return $this->requestMethod() == 'PATCH';
|
||
}
|
||
|
||
/**
|
||
* HEAD
|
||
* @return boolean
|
||
*/
|
||
public function isOptions()
|
||
{
|
||
return $this->requestMethod() == 'OPTIONS';
|
||
}
|
||
|
||
/**
|
||
* AJAX
|
||
* @return boolean
|
||
*/
|
||
public function isAjax()
|
||
{
|
||
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && ($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest');
|
||
}
|
||
|
||
/**
|
||
* 创建一个请求(post或get取决于data是否有值且不为空或空数组)
|
||
* @param string $url
|
||
* @param array $data
|
||
* @param array $header
|
||
* @return boolean
|
||
*/
|
||
public function create($url, $data = [], $header = [])
|
||
{
|
||
return create_http_request($url, $data, $header);
|
||
}
|
||
|
||
/**
|
||
* 获取客户端IP
|
||
* @param int $type
|
||
* @param bool $client
|
||
* @return mixed
|
||
*/
|
||
public function ip($type = 0, $client = true)
|
||
{
|
||
return get_client_ip($type, $client);
|
||
}
|
||
|
||
/**
|
||
* 模块名称
|
||
* @return mixed
|
||
*/
|
||
public function module()
|
||
{
|
||
return $this->router->module;
|
||
}
|
||
|
||
/**
|
||
* 控制器完整类名
|
||
* @return mixed
|
||
*/
|
||
public function classname()
|
||
{
|
||
return $this->router->class;
|
||
}
|
||
|
||
/**
|
||
* 控制器名称
|
||
* @return mixed
|
||
*/
|
||
public function controller()
|
||
{
|
||
return $this->router->ctrl;
|
||
}
|
||
|
||
/**
|
||
* 方法名称
|
||
* @return mixed
|
||
*/
|
||
public function method()
|
||
{
|
||
return $this->router->method;
|
||
}
|
||
|
||
/**
|
||
* 参数
|
||
* @return mixed
|
||
*/
|
||
public function params()
|
||
{
|
||
return $this->router->params;
|
||
}
|
||
|
||
/**
|
||
* 移除值
|
||
* @param $field
|
||
* @return $this
|
||
*/
|
||
public function except($field = null)
|
||
{
|
||
if (is_array($field)) {
|
||
$this->except = array_merge($this->except, $field);
|
||
} elseif ($field) {
|
||
$this->except[] = $field;
|
||
}
|
||
return $this;
|
||
}
|
||
|
||
/**
|
||
* GET数据
|
||
* @param null $name
|
||
* @param array $except
|
||
* @param string $filter
|
||
* @return null
|
||
*/
|
||
public function get($name = '*', $except = [], $filter = 'filter')
|
||
{
|
||
return $this->requestData('get', $name, $except, $filter);
|
||
}
|
||
|
||
/**
|
||
* POST数据
|
||
* @param null $name
|
||
* @param array $except
|
||
* @param string $filter
|
||
* @return null
|
||
*/
|
||
public function post($name = '*', $except = [], $filter = 'filter')
|
||
{
|
||
return $this->requestData('post', $name, $except, $filter);
|
||
}
|
||
|
||
/**
|
||
* GET POST公共方法
|
||
* @param $type
|
||
* @param $name
|
||
* @param $except
|
||
* @param $filter
|
||
* @return null
|
||
*/
|
||
private function requestData($type, $name, $except, $filter)
|
||
{
|
||
$data = ($type == 'get') ? $_GET : $_POST;
|
||
$name = ($name == '*') ? null : $name;
|
||
|
||
if (!is_array($except)) {
|
||
$except = explode(',', $except);
|
||
}
|
||
|
||
$this->except = array_merge($this->except, $except);
|
||
// 移除指定的值
|
||
foreach ($this->except as $key => $value) {
|
||
if (isset($data[$value])) {
|
||
unset($data[$value]);
|
||
}
|
||
}
|
||
|
||
// 重置except的值
|
||
$this->except = [];
|
||
|
||
filterArray($data, $filter, $data);
|
||
|
||
if ($name) {
|
||
if (isset($data[$name])) {
|
||
return $data[$name];
|
||
} else {
|
||
return null;
|
||
}
|
||
} else {
|
||
return $data;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 设置中间件
|
||
* @param MiddlewareIfs $middleware
|
||
*/
|
||
private function middleware(MiddlewareIfs $middleware)
|
||
{
|
||
$this->middleware[] = $middleware;
|
||
}
|
||
|
||
/**
|
||
* 中间件前置方法
|
||
*/
|
||
private function beforeRoute()
|
||
{
|
||
foreach ($this->middleware as $middleware) {
|
||
$returnData = $middleware->before();
|
||
if ($returnData !== true) {
|
||
return $returnData;
|
||
}
|
||
unset($returnData);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* 中间件后置方法
|
||
* @param $data
|
||
*/
|
||
private function afterRoute($data)
|
||
{
|
||
$this->middleware = array_reverse($this->middleware);
|
||
foreach ($this->middleware as $middleware) {
|
||
$middleware->after($data);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 指定路由驱动
|
||
* @param $type
|
||
* @return string|Command|Pathinfo
|
||
*/
|
||
private function routeDriver($type)
|
||
{
|
||
$routeDriver = '';
|
||
if (php_sapi_name() == 'cli') {
|
||
// 命令行运行程序
|
||
$routeDriver = new Command();
|
||
} else {
|
||
// 其他方式
|
||
switch ($type) {
|
||
case 1:
|
||
$routeDriver = new Pathinfo();
|
||
break;
|
||
default:
|
||
// 其他
|
||
}
|
||
}
|
||
return $routeDriver;
|
||
}
|
||
|
||
/**
|
||
* 设置路由并执行程序
|
||
* @param $type
|
||
* @param $defaultModule
|
||
* @return mixed
|
||
* @throws \top\library\exception\RouteException
|
||
*/
|
||
public function execute($type, $defaultModule)
|
||
{
|
||
// 实例化路由,并执行对应方法
|
||
$routeDriver = $this->routeDriver($type);
|
||
$this->router = (new Router($routeDriver, $defaultModule))->handler();
|
||
|
||
$userMiddleware = Register::get('Config')->get('middleware');
|
||
$systemMiddleware = [Init::class, View::class];
|
||
|
||
$middleware = array_merge($systemMiddleware, $userMiddleware);
|
||
foreach ($middleware as $key => $value) {
|
||
$this->middleware(new $value());
|
||
}
|
||
|
||
$data = $this->runAction();
|
||
return $data;
|
||
}
|
||
|
||
/**
|
||
* 调用对应方法
|
||
* @return mixed
|
||
* @throws \ReflectionException
|
||
*/
|
||
private function runAction()
|
||
{
|
||
$middlewareData = $this->beforeRoute();
|
||
|
||
if ($middlewareData === true) {
|
||
$ctrl = $this->router->class;
|
||
$method = $this->router->method;
|
||
$params = $this->router->params;
|
||
|
||
$data = null;
|
||
$object = new $ctrl();
|
||
$reflectionClass = new \ReflectionClass($ctrl);
|
||
if ($reflectionClass->hasMethod('_init')) {
|
||
$data = $object->_init();
|
||
}
|
||
|
||
if ($data === null || $data === '') {
|
||
// 前置方法
|
||
$beforeReturnData = null;
|
||
$beforeMethod = 'before_' . $method;
|
||
if ($reflectionClass->hasMethod($beforeMethod)) {
|
||
$beforeReturnData = $object->{$beforeMethod}();
|
||
}
|
||
|
||
if ($beforeReturnData === null || $beforeReturnData === '' || $beforeReturnData === true) {
|
||
$reflectionMethod = new \ReflectionMethod($ctrl, $method);
|
||
$data = $reflectionMethod->invokeArgs($object, $params);
|
||
|
||
// 后置方法
|
||
$afterMethod = 'after_' . $method;
|
||
if ($reflectionClass->hasMethod($afterMethod)) {
|
||
$object->{$afterMethod}();
|
||
}
|
||
} else {
|
||
$data = $beforeReturnData;
|
||
}
|
||
}
|
||
} else {
|
||
$data = $middlewareData;
|
||
}
|
||
|
||
$this->afterRoute($data);
|
||
|
||
return $data;
|
||
}
|
||
|
||
public function __destruct()
|
||
{
|
||
}
|
||
}
|