PHP DIY 系列------框架篇:2. 請求與輸出

13sai發表於2020-02-20

我們在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';
    }

    /**
     * 請求頭
     * @param $name
     * @param null $defaultValue
     * @return mixed|null
     */
    public function getHeader($name, $defaultValue = null)
    {
        $name = ucfirst($name);
        if (function_exists('apache_request_headers')) {
            $headers = apache_request_headers();
            return $headers[$name]?? $defaultValue;
        }
        $name = strtoupper($name);
        return $_SERVER[$name]?? $defaultValue;
    }

    /**
     * 獲取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);
    }

    public function getQueryParam($name, $defaultValue = null)
    {
        $params = $this->getQueryParams();
        return isset($params[$name]) ? $params[$name] : $defaultValue;
    }

    public function getQueryParams()
    {
        if (empty($this->queryParams)) {
            return $this->queryParams = $_GET;
        }
        return $this->queryParams;
    }

    /**
     * 獲取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);
    }

    public function getBodyParam($name, $defaultValue = null)
    {
        $params = $this->getBodyParams();
        if (is_object($params)) {
            try {
                return $params->{$name};
            } catch (\Exception $e) {
                return $defaultValue;
            }
        }
        return isset($params[$name]) ? $params[$name] : $defaultValue;
    }

    public function getBodyParams()
    {
        $contentType = strtolower($this->getHeader('Content-Type'));
        if ($contentType == 'multipart/form-data') {
            $this->bodyParams = $_POST;
        } else {
            $this->bodyParams = \json_decode(file_get_contents("php://input"), true);
        }
        return $this->bodyParams?? [];
    }

    /**
     * get引數陣列
     */
    private $queryParams = [];

    /**
     * post引數陣列
     */
    private $bodyParams = [];

    private $method;
}

知識點:

  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’]

Response

Response預設以使用廣泛的json輸出,暫時也只考慮json格式輸出的情況。

<?php
/**
 * 資料輸出
 */

namespace Library\Https;

use Library\Components\Base;

class Response extends Base
{
    public $code = 0;

    public $result = [];

    public $msg = "success";

    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;
    }
}

知識點:

  1. header() 用於傳送原生的 HTTP 頭。
  2. json_encode ( mixed $value [, int $options = 0 [, int $depth = 512 ]] ) : string — 對變數進行 JSON 編碼,options可以預定義常量,如 JSON_UNESCAPED_UNICODE,JSON_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應用裡的控制器都必須繼承這個基類控制器。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

分享開發知識,歡迎交流。qq957042781

相關文章