请求模块

从零开始编写一个PHP框架 系列的《请求模块》

项目地址:terse

前言

当我们打开一个网页,浏览器会发出很多请求,有的是请求文件,有的是请求接口。

在编写和处理接口相关问题的时候,难免会需要分析请求相关的事情,比如:请求类型、请求头、请求相关的数据等。

需求分析

主要从几个大的方面来区分。

  • 服务器相关变量的获取
  • 请求类型的获取
  • 请求参数的获取

文件结构

├── Interfaces
│   └── Request.php    [接口]
└── Request.php        [请求类]

为了规范一点,以后的模块尽量都加上相关接口。

由于这里接口的函数和子类的函数一致,这里就不重复写了。

服务器相关变量的获取

众所周知,服务端相关的变量都是从 $_SERVER 里获取的。所以我们需要对外提供一个 getServer 的接口。

为了使用方便,我们要将一些经常用到的参数,封装好方法给暴露给外界。

getServer($name);
        if ($result) {
            return $result;
        }
        return $this->getServer('HTTP_' . $name);
    }

    /**
     * 获取 HTTP schema (http/https)
     *
     * @return string
     */
    public function getScheme()
    {
        $https = $this->getServer('HTTPS');
        return $https && $https != 'off' ? 'https' : 'http';
    }

    /**
     * 获取服务器IP
     *
     * @return string
     */
    public function getServerAddress()
    {
        $serverAddress = $this->getServer('SERVER_ADDR');
        return $serverAddress ? $serverAddress : gethostbyname('localhost');
    }

    /**
     * 获取服务器名称
     *
     * @return string
     */
    public function getServerName()
    {
        $serverName = $this->getServer('SERVER_NAME');
        return $serverName ? $serverName : 'localhost';
    }

    /**
     * 获取请求头中 Host: 项的内容
     *
     * @return string
     */
    public function getHttpHost()
    {
        return $this->getServer('HTTP_HOST');
    }

    /**
     * 获取端口
     *
     * @return int
     */
    public function getPort()
    {
        return $this->getServer('SERVER_PORT');
    }

    /**
     * 获取URI
     * 
     * @return string
     */
    public final function getURI()
    {
        return $this->getServer('REQUEST_URI');
    }

    /**
     * 获取客户端IP
     *
     * @return string
     */
    public function getClientAddress()
    {
        return $this->getServer('REMOTE_ADDR');
    }

    /**
     * 获取 UA
     *
     * @return string
     */
    public function getUserAgent()
    {
        return $this->getServer('HTTP_USER_AGENT');
    }

    /**
     * 获取 http referer
     *
     * @return string
     */
    public function getHttpReferer()
    {
        return $this->getServer('HTTP_REFERER');
    }

    /**
     * 获取请求方式
     *
     * @return string
     */
    public function getMethod()
    {
        $method = $this->getServer('REQUEST_METHOD');
        // 判断 是否存在
        return $this->isValidMethod($method) ? $method : self::METHOD_GET;
    }
}

请求类型的获取

关于请求类型,除了我们常用的 GETPOST 之外,还有一些像 OPTIONSPUTDELETEPATCHHEAD 等。

为了辨别请求是不是相关类型,我们需要有个函数作为判断,比如 is*

getMethod() === self::METHOD_GET;
    }

    /**
     * 判断是否 POST
     *
     * @return bool
     */
    public function isPost()
    {
        return $this->getMethod() === self::METHOD_POST;
    }

    /**
     * 判断是否 PUT
     *
     * @return bool
     */
    public function isPut()
    {
        return $this->getMethod() === self::METHOD_PUT;
    }

    /**
     * 判断是否 DELETE
     *
     * @return bool
     */
    public function isDelete()
    {
        return $this->getMethod() === self::METHOD_DELETE;
    }

    /**
     * 判断是否 HEAD
     *
     * @return bool
     */
    public function isHead()
    {
        return $this->getMethod() === self::METHOD_HEAD;
    }

    /**
     * 判断是否 OPTIONS
     *
     * @return bool
     */
    public function isOptions()
    {
        return $this->getMethod() === self::METHOD_OPTIONS;
    }

    /**
     * 判断是否 PATCH
     *
     * @return bool
     */
    public function isPatch()
    {
        return $this->getMethod() === self::METHOD_PATCH;
    }

    /**
     * 获取请求方式
     *
     * @return string
     */
    public function getMethod()
    {
        $method = $this->getServer('REQUEST_METHOD');
        // 判断 是否存在
        return $this->isValidMethod($method) ? $method : self::METHOD_GET;
    }

    /**
     * 检查方法
     *
     * @param string $method
     * @return bool
     */
    protected function isValidMethod($method)
    {
        switch ($method) {
            case self::METHOD_GET:
            case self::METHOD_POST:
            case self::METHOD_PUT:
            case self::METHOD_DELETE:
            case self::METHOD_HEAD:
            case self::METHOD_OPTIONS:
            case self::METHOD_PATCH:
            case self::METHOD_PURGE:
            case self::METHOD_TRACE:
            case self::METHOD_CONNECT:
                return true;
        }
        return false;
    }
}

请求参数的获取

关于请求参数,这里有几种类型:REQUESTGETPOSTPUTRAW INPUTFILES

getHelper($_REQUEST, $name, $filters, $default);
    }

    /**
     * 获取 $_POST 参数
     *
     * @param string       $name
     * @param string|array $filters
     * @param mixed        $default
     * @return mixed
     */
    public function getPost($name = null, $filters = null, $default = null)
    {
        return $this->getHelper($_POST, $name, $filters, $default);
    }

    /**
     * 获取 $_GET 参数
     *
     * @param string       $name
     * @param string|array $filters
     * @param mixed        $default
     * @return mixed
     */
    public function getQuery($name = null, $filters = null, $default = null)
    {
        return $this->getHelper($_GET, $name, $filters, $default);
    }

    /**
     * 获取上传的文件
     *
     * @return boolean
     */
    public function getFiles()
    {
        return $_FILES;
    }

    /**
     * Gets HTTP raw request body
     *
     * @return string
     */
    public function getRawBody()
    {
        if (!$this->_rawBody) {
            $this->_rawBody = @file_get_contents('php://input');
        }
        return $this->_rawBody;
    }

    /**
     * Gets HTTP raw request body
     *
     * @return string
     */
    public function getJsonRawBody()
    {
        $rawBody = $this->getRawBody();
        return @json_decode($rawBody, true);
    }

    /**
     * 判断参数是否存在,并启用过滤
     * 
     * @param  array  $source
     * @param  string $name
     * @param  array  $filters
     * @param  mixed  $default
     * @return mixed
     */
    protected final function getHelper(array $source, $name, $filters, $default)
    {
        if (!$name) {
            return $source;
        }

        $value = $default;
        if (isset($source[$name])) {
            $value = $source[$name];
        }

        // 本来想写filter的,这个放到第二期再做吧
        if (!!$filters) {
            # filter
        }

        return !$value && $default ? $default : $value;
    }
}

有时候,我们需要判断某个参数是否存在,所以我们需要提供 has* 方法。

其它

由于我们经常使用 Ajax,所以请求里面也提供了 isAjax 的接口供外界调用。

getServer('HTTP_X_REQUESTED_WITH');
        return strtoupper($httpXRequest) == "XMLHTTPREQUEST";
    }
}

完整代码

目前考虑的就是这些方法,在实际应用中,如果不够,则会不断的添加方法。


*/
class Request implements RequestInterface
{
    const METHOD_GET = 'GET';
    const METHOD_POST = 'POST';
    const METHOD_PUT = 'PUT';
    const METHOD_DELETE = 'DELETE';
    const METHOD_HEAD = 'HEAD';
    const METHOD_OPTIONS = 'OPTIONS';
    const METHOD_PATCH = 'PATCH';
    const METHOD_PURGE = 'PURGE';
    const METHOD_TRACE = 'TRACE';
    const METHOD_CONNECT = 'CONNECT';

    protected $_rawBody;

    /**
     * 获取 $_REQUEST 参数
     *
     * @param string       $name
     * @param string|array $filters
     * @param mixed        $default
     * @return mixed
     */
    public function get($name = null, $filters = null, $default = null)
    {
        return $this->getHelper($_REQUEST, $name, $filters, $default);
    }

    /**
     * 获取 $_POST 参数
     *
     * @param string       $name
     * @param string|array $filters
     * @param mixed        $default
     * @return mixed
     */
    public function getPost($name = null, $filters = null, $default = null)
    {
        return $this->getHelper($_POST, $name, $filters, $default);
    }

    /**
     * 获取 $_GET 参数
     *
     * @param string       $name
     * @param string|array $filters
     * @param mixed        $default
     * @return mixed
     */
    public function getQuery($name = null, $filters = null, $default = null)
    {
        return $this->getHelper($_GET, $name, $filters, $default);
    }

    /**
     * 获取上传的文件
     *
     * @return boolean
     */
    public function getFiles()
    {
        return $_FILES;
    }

    /**
     * Gets HTTP raw request body
     *
     * @return string
     */
    public function getRawBody()
    {
        if (!$this->_rawBody) {
            $this->_rawBody = @file_get_contents('php://input');
        }
        return $this->_rawBody;
    }

    /**
     * Gets HTTP raw request body
     *
     * @return string
     */
    public function getJsonRawBody()
    {
        $rawBody = $this->getRawBody();
        return @json_decode($rawBody, true);
    }

    /**
     * 检查 $_REQUEST 中是否存在指定参数
     *
     * @param string $name
     * @return bool
     */
    public function has($name)
    {
        return isset($_REQUEST[$name]);
    }

    /**
     * 检查 $_POST 中是否存在指定参数
     *
     * @param string $name
     * @return bool
     */
    public function hasPost($name)
    {
        return isset($_POST[$name]);
    }

    /**
     * 检查 $_GET 中是否存在指定参数
     *
     * @param string $name
     * @return bool
     */
    public function hasQuery($name)
    {
        return isset($_GET[$name]);
    }

    /**
     * 检查 $_SERVER 中是否存在指定参数
     *
     * @param string $name
     * @return bool
     */
    public function hasServer($name)
    {
        return isset($_SERVER[$name]);
    }

    /**
     * 判断是否存在上传文件
     *
     * @return boolean
     */
    public function hasFiles()
    {
        return !!$_FILES;
    }

    /**
     * 获取 $_SERVER 参数
     *
     * @param string $name
     * @return mixed
     */
    public function getServer($name)
    {
        if (isset($_SERVER[$name])) {
            return $_SERVER[$name];
        }
        return null;
    }

    /**
     * 获取 Header 信息
     *
     * @param string $name
     * @return string
     */
    public function getHeader($header)
    {
        $name = strtoupper(strtr($header, "-", "_"));
        $result = $this->getServer($name);
        if ($result) {
            return $result;
        }
        return $this->getServer('HTTP_' . $name);
    }

    /**
     * 获取 HTTP schema (http/https)
     *
     * @return string
     */
    public function getScheme()
    {
        $https = $this->getServer('HTTPS');
        return $https && $https != 'off' ? 'https' : 'http';
    }

    /**
     * 获取服务器IP
     *
     * @return string
     */
    public function getServerAddress()
    {
        $serverAddress = $this->getServer('SERVER_ADDR');
        return $serverAddress ? $serverAddress : gethostbyname('localhost');
    }

    /**
     * 获取服务器名称
     *
     * @return string
     */
    public function getServerName()
    {
        $serverName = $this->getServer('SERVER_NAME');
        return $serverName ? $serverName : 'localhost';
    }

    /**
     * 获取请求头中 Host: 项的内容
     *
     * @return string
     */
    public function getHttpHost()
    {
        return $this->getServer('HTTP_HOST');
    }

    /**
     * 获取端口
     *
     * @return int
     */
    public function getPort()
    {
        return $this->getServer('SERVER_PORT');
    }

    /**
     * 获取URI
     * 
     * @return string
     */
    public final function getURI()
    {
        return $this->getServer('REQUEST_URI');
    }

    /**
     * 获取客户端IP
     *
     * @return string
     */
    public function getClientAddress()
    {
        return $this->getServer('REMOTE_ADDR');
    }

    /**
     * 获取 UA
     *
     * @return string
     */
    public function getUserAgent()
    {
        return $this->getServer('HTTP_USER_AGENT');
    }

    /**
     * 获取 http referer
     *
     * @return string
     */
    public function getHttpReferer()
    {
        return $this->getServer('HTTP_REFERER');
    }

    /**
     * 获取请求方式
     *
     * @return string
     */
    public function getMethod()
    {
        $method = $this->getServer('REQUEST_METHOD');
        // 判断 是否POST
        if ($method === self::METHOD_POST) {
            $method = $this->validPost();
        }
        // 判断 是否存在
        return $this->isValidMethod($method) ? $method : self::METHOD_GET;
    }

    /**
     * 判断是否 GET
     *
     * @return bool
     */
    public function isGet()
    {
        return $this->getMethod() === self::METHOD_GET;
    }

    /**
     * 判断是否 POST
     *
     * @return bool
     */
    public function isPost()
    {
        return $this->getMethod() === self::METHOD_POST;
    }

    /**
     * 判断是否 PUT
     *
     * @return bool
     */
    public function isPut()
    {
        return $this->getMethod() === self::METHOD_PUT;
    }

    /**
     * 判断是否 DELETE
     *
     * @return bool
     */
    public function isDelete()
    {
        return $this->getMethod() === self::METHOD_DELETE;
    }

    /**
     * 判断是否 HEAD
     *
     * @return bool
     */
    public function isHead()
    {
        return $this->getMethod() === self::METHOD_HEAD;
    }

    /**
     * 判断是否 OPTIONS
     *
     * @return bool
     */
    public function isOptions()
    {
        return $this->getMethod() === self::METHOD_OPTIONS;
    }

    /**
     * 判断是否 PATCH
     *
     * @return bool
     */
    public function isPatch()
    {
        return $this->getMethod() === self::METHOD_PATCH;
    }

    /**
     * 判断是否 AJAX
     *
     * @return bool
     */
    public function isAjax()
    {
        $httpXRequest = $this->getServer('HTTP_X_REQUESTED_WITH');
        return strtoupper($httpXRequest) == "XMLHTTPREQUEST";
    }

    /**
     * 待写
     */
    protected function validPost()
    {
        return self::METHOD_POST;
    }

    /**
     * 检查方法
     *
     * @param string $method
     * @return bool
     */
    protected function isValidMethod($method)
    {
        switch ($method) {
            case self::METHOD_GET:
            case self::METHOD_POST:
            case self::METHOD_PUT:
            case self::METHOD_DELETE:
            case self::METHOD_HEAD:
            case self::METHOD_OPTIONS:
            case self::METHOD_PATCH:
            case self::METHOD_PURGE:
            case self::METHOD_TRACE:
            case self::METHOD_CONNECT:
                return true;
        }
        return false;
    }

    /**
     * 判断参数是否存在,并启用过滤
     * 
     * @param  array  $source
     * @param  string $name
     * @param  array  $filters
     * @param  mixed  $default
     * @return mixed
     */
    protected final function getHelper(array $source, $name, $filters, $default)
    {
        if (!$name) {
            return $source;
        }

        $value = $default;
        if (isset($source[$name])) {
            $value = $source[$name];
        }

        if (!!$filters) {
            # filter
        }

        return !$value && $default ? $default : $value;
    }
}

调用方式

get();
$request->getPost();
$request->getQuery();
$request->getJsonRawBody();
$request->isGet();
$request->isPost();
$request->isAjax();

最后

通篇基本在贴代码了,毕竟基本是判断和获取,没有什么比较特别的东西在里面。

下一篇《路由模块》

你可能感兴趣的:(请求模块)