同福

做个web框架(14)——响应对象TFResponse(二)实现响应对象【20201109】

介绍

介绍

上一课童鞋们和福哥学习了TFPHP的响应对象TFRespnose涉及到的一些知识,包括:响应状态、响应数据类型、响应数据长度等等,在响应对象里面我们要对这些数据进行管理控制。这里面响应状态包含非常多的可选状态信息,所以福哥将响应状态封装了一个新对象TFResponseStatus。然后响应数据类型和响应数据长度相对比较简单,福哥直接在TFResponse对象里面实现了。

完成了TFResponse对象之后,发现控制器对象TFController的用于实现接口资源的方法不是很合理,这里面分开了用于JSON数据的responseJson方法和用于其他数据的response方法。同时load方法也进行了改造。

代码

TFResponseStatus

属性

private array $statusArr = array(
    100=>"Continue",
    101=>"Switching Protocols",
    102=>"Processing",
    200=>"OK",
    201=>"Created",
    202=>"Accepted",
    203=>"Non-Authoritative Information",
    204=>"No Content",
    205=>"Reset Content",
    206=>"Partial Content",
    207=>"Multi-Status",
    300=>"Multiple Choices",
    301=>"Moved Permanently",
    302=>"Move temporarily",
    303=>"See Other",
    304=>"Not Modified",
    305=>"Use Proxy",
    306=>"Switch Proxy",
    307=>"Temporary Redirect",
    400=>"Bad Request",
    401=>"Unauthorized",
    402=>"Payment Required",
    403=>"Forbidden",
    404=>"Not Found",
    405=>"Method Not Allowed",
    406=>"Not Acceptable",
    407=>"Proxy Authentication Required",
    408=>"Request Timeout",
    409=>"Conflict",
    410=>"Gone",
    411=>"Length Required",
    412=>"Precondition Failed",
    413=>"Request Entity Too Large",
    414=>"Request-URI Too Long",
    415=>"Unsupported Media Type",
    416=>"Requested Range Not Satisfiable",
    417=>"Expectation Failed",
    421=>"Too Many Connections",
    422=>"Unprocessable Entity",
    423=>"Locked",
    424=>"Failed Dependency",
    425=>"Unordered Collection",
    426=>"Upgrade Required",
    449=>"Retry With",
    451=>"Unavailable For Legal Reasons",
    500=>"Internal Server Error",
    501=>"Not Implemented",
    502=>"Bad Gateway",
    503=>"Service Unavailable",
    504=>"Gateway Timeout",
    505=>"HTTP Version Not Supported",
    506=>"Variant Also Negotiates",
    507=>"Insufficient Storage",
    509=>"Bandwidth Limit Exceeded",
    510=>"Not Extended",
    600=>"Unparseable Response Headers",
);

set

public function set(int $code): bool {
    if(isset($this->statusArr[$code])){
        $this->code = $code;
        $this->message = $this->statusArr[$code];

        return true;
    }

    return false;
}

response

public function response(){
    header("HTTP/1.1 ". $this->code. " ". $this->message);
}

TFResponse

responseStatus

public function responseStatus(int $code){
    $responseStatus = new TFResponseStatus($code);
    $responseStatus->response();
}

responseContentType

public function responseContentType(string $mimeType, string $charset=null, bool $disableCharset=false){
    if($charset == null){
        $charset = "UTF-8";
    }
    if($disableCharset){
        header("Content-Type: ". $mimeType);
    }
    else{
        header("Content-Type: ". $mimeType. "; charset=". $charset);
    }
}

responseContentLength

public function responseContentLength(int $length){
    header("Content-Length: ". $length);
}

responseUDF

public function responseUDF(string $key, string $value){
    header($key. ": ". $value);
}

TFController

response

protected function response(int $statusCode=null, int $dataLength=null, string $mimeType=null, string $charset=null, bool $disableCharset=false){
    $myResponse = new TFResponse();

    // status code
    if($statusCode == null){
        $statusCode = 200;
    }

    // content length
    if($dataLength === null){
        $dataLength = 0;
    }

    // content type
    if($mimeType == null){
        $mimeType = "text/plain";
    }

    // charset
    $charset = strtoupper($charset);
    $systemCharset = strtoupper(TFConfig::get("charset", "system"));
    if($charset == null){
        $charset = $systemCharset;
    }

    // header
    $myResponse->responseStatus($statusCode);
    $myResponse->responseContentType($mimeType, $charset, $disableCharset);
    $myResponse->responseContentLength($dataLength);
}

responseJson

protected function responseJson(int $code, string $msg, int $statusCode=null, string $charset=null){
    $myResponse = new TFResponse();

    // status code
    if($statusCode == null){
        $statusCode = 200;
    }

    // charset
    $charset = strtoupper($charset);
    $systemCharset = strtoupper(TFConfig::get("charset", "system"));
    if($charset == null){
        $charset = $systemCharset;
    }

    // header
    $myResponse->responseStatus($statusCode);
    $myResponse->responseContentType("application/json", $charset);

    // data
    $statData = array(
        'errcode'=>$code,
        'errmsg'=>$msg,
    );
    $this->data = array_merge($statData, $this->data);
    $jsonData = json_encode($this->data);
    if($charset != $systemCharset){
        $jsonData = mb_convert_encoding($jsonData, $charset, $systemCharset);
    }
    echo $jsonData;
}

load

public function load($uri, $extension, $mappingFilePath){
    $this->process();
}

讲解

这一课更新的内容有点多,福哥来给大家一一讲解一下。

TFResponseStatus

属性

福哥在TFResponseStatus对象里面将全部响应状态码封装到一个数组里面了,以方便后面使用。

set

通过set方法可以设置响应状态码。

response

通过response方法可以将响应状态推送给客户端(浏览器)。

TFResponse

responseStatus

这个方法会创建TFResponseStatus对象的实例,并将响应状态推送给客户端。

responseContentType

这个方法会推送数据类型给客户端。

responseContentLength

这个方法会推送数据长度给客户端(注意:如果不调用这个方法系统默认会使用chunked方式响应)。

responseUDF

这个方法可以自定义更多的响应头信息。

TFController

response

这个方法包含$mimeType参数,可以用作任意类型的数据的响应处理。

responseJson

这个方法专门用作JSON数据的响应处理。

process

这个方法的类型重新设计了,不再返回任何值了。

load

去掉了原来在这里直接进行响应处理的逻辑,响应处理交给业务控制器自己控制。

使用

现在我们改造一下api/member/status接口的逻辑,测试一下我们的响应对象。

代码

protected function process(){
    $myRequest = new TFRequest();

    switch($myRequest->get->get("type")){
        case "200":
            $this->data = array(
                'user'=>array(
                    'userid'=>123456,
                    'username'=>"福哥",
                )
            );
            $this->responseJson(0, "OK", 200);
            break;
        case "404":
            $this->responseJson(1, "User data is missing", 404);
            break;
        case "401":
            $this->responseJson(2, "Not login", 401);
            break;
        case "403":
            $this->responseJson(3, "Not permit", 403);
            break;
        case "500":
            $this->responseJson(5, "Exception", 401);
            break;
    }
}

200

8878bc315f8b999a.jpg

404

ed3ebbce9072165c.jpg

401

c5a0dac07d77a92f.jpg

403

0f8c1f4c439e056e.jpg

500

4253c89983956e41.jpg

总结

今天我们实现了TFPHP的TFResponse对象的全部功能,通过这个对象可以自由地控制返回给浏览器的数据。不过在网页控制器PageController里响应请求是交给Smarty模板对象处理的,除非特殊情况我们都不需要自己调用响应方法。

下一课我们开始准备利用我们的TFPHP框架开发一套标准的用户认证系统项目,一个好用的web框架一定是经过无数个实际项目的千锤百炼才能成功的~~