手写一个php api框架[5] -- 请求与输出

67 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情

前面一个我们梳理了目录结果,这一节我们在library\Https目录下新建Request、Response,开始编写请求和输出的代码。

Request

我们实现几个常用的方法,get、post、method等,这里主要用$_SERVER实现,为了复用我们定义了三个私有属性存储get参数、post参数和method。

<?php
/**
 * 处理请求
 */

namespace Library\Https;

use Library\Components\Base;

class Request extends Base
{
    /**
     * 获取请求方法
     * @return string
     */
    public function getMethod()
    {
        if (isset($_SERVER['REQUEST_METHOD'])) {
            return strtoupper($_SERVER['REQUEST_METHOD']);
        }
        return 'GET';
    }

    ...

    /**
     * 获取get参数
     * @param null $name
     * @param null $defaultValue
     * @return |null
     */
    public function get($name = null, $defaultValue = null)
    {
        if ($name === null) {
            return $this->getQueryParams();
        }
        return $this->getQueryParam($name, $defaultValue);
    }

    ...

    /**
     * 获取post参数
     * @param null $name
     * @param null $defaultValue
     * @return array|mixed|null
     */
    public function post($name = null, $defaultValue = null)
    {
        if ($name === null) {
            return $this->getBodyParams();
        }
        return $this->getBodyParam($name, $defaultValue);
    }

    ...

    /**
     * get参数数组
     */
    private $queryParams = [];

    /**
     * post参数数组
     */
    private $bodyParams = [];

    private $method;
}


完整代码参考:github.com/13sai/saiAP…

知识点:

  1. 获取请求头部信息的方式nginx和apache不同
  • apache可以使用apache_request_headers
  • nginx使用$SERVER,并且需要注意的是的是自定义信息等参数会在前面自动加上http,并且会转换为大写 server
  1. post参数获取的方式
  • 当Content-Type是application/x-www-data-urlencodedmultipart/form-data时,数据会放进$_POST中;
  • 除了Coentent-Type为multipart/form-data的情况,数据都可以通过file_get_contents("php://input")取到;
  • 不建议使用$GLOBALS['HTTP_RAW_POST_DATA'],php7 已移除此变量

Response

Response默认以使用广泛的json输出,暂时也只考虑json格式输出的情况。后续可以按需要自行拓展,这一块比较简单,就不赘述了,主要代码如下:

<?php
/**
 * 数据输出
 */

namespace Library\Https;

use Library\Components\Base;

class Response extends Base
{
    ...

    public function send()
    {
        header('Content-Type:application/json; charset=utf-8');
        echo \json_encode([
            'data' => $this->result,
            'msg' => $this->msg,
            'code' => $this->code,
            'timestamp' => time()
        ]);
    }

    public function json($data = [])
    {
        $this->result = array_merge($this->result, $data);
        return $this;
    }
}

完整代码参考:github.com/13sai/saiAP…

知识点:

  1. header() 用于发送原生的 HTTP 头。
  2. json_encode ( mixed $value [, int $options = 0 [, int $depth = 512 ]] ) : string — 对变量进行 JSON 编码,options可以预定义常量,如 JSON_UNESCAPED_UNICODEJSON_UNESCAPED_SLASHES

Controller

既然请求输出都已经完成了,我们不妨创建一个基类控制器,也放在相同的Https目录,我们创建一个构造函数,实例化一个Response,并实现一个通用的json:

<?php
/**
 * 基类控制器
 * 预定义json方法,便于其他控制器使用
 * 返回格式
 {
    "data": [],
    "msg": "success",
    "code": 0,
    "timestamp": 1572231957
}
 */

namespace Library\Https;

class Controller
{
    protected $response;

    protected $code = 200;

    public function __construct()
    {
        $this->response = new Response();
    }

    public function json($data = [])
    {
        return $this->response->json($data);
    }

    public function index($params)
    {
        return $this->response->json(['hello' => 'saif']);
    }
}

我们规定 app 应用里的控制器都必须继承这个基类控制器。

就这样,我们在这一节已经完成了请求输出与控制器,迈出了一大步。