SWOOLE 从入门到放弃之写个小框架(十五)

小框架里处理http和websocket是分两条线来实的,主要是为了减少代码的复杂度。然后这两种不同的业务线是要应对的不同场景的,不同的场景所涉及到的方法、对象、属性等等 都不同。http的控制器主要包含路由信息、http请求对象$request,http响应对象$response,在一些特定场景下,还需要直接使用$server对象,以及$task任务对象。同时还必须至少具备两个方法,第一个是模板渲染方法 display,第二是个json输出方法。而websocket的控制器就很简单了,路由信息,$server对象,数据帧$frame以及任务对象。

首先,创建frame/Lib/Controller.php,代码如下

<?php
/**
 * http Controller
 */
namespace Piz;
class Controller
{
    /**
     * @var \Piz\Router
     */
    protected $router;
    /**
     * @var swoole_http_server->request
     */
    protected $request;
    /**
     * @var swoole_http_server->response
     */
    protected $response;
    /**
     * @var swoole_server
     */
    protected $server;
    /**
     * @var swoole_server->task
     */
    protected $task;
    /**
     * 渲染输出JSON
     * @param array $array
     * @param null  $callback
     */
    final public function json($array=array(),$callback=null){
        $this->gzip ();
        $this->response->header('Content-type','application/json');
        $json = json_encode($array);
        $json = is_null($callback) ? $json : "{$callback}({$json})" ;
        $this->response->end($json);
    }

    /**
     * 渲染模板
     * @param null $file 为空时,
     * @param bool $return true 返回值,false 仅include
     * @return string
     */
    final public function display($param = array() ,$return = false){
        if(!is_array ($param)){
            Log::get_instance()->write('WARNING',"参数类型必须为key=>val式的数组");
        }
        extract($param);
        $this->gzip ();
        $path = Config::get_instance()->get('app.path').'/tpl/'.$this->route['m'].'/'.$this->route['c'] .'/'.$this->route['a'].'.php';
        if(!file_exists ($path)){
            $this->response->status(404);
            $this->response->end("模板不存在:".$path);
            Log::get_instance()->write('WARNING',"模板不存在",$path);
            return ;
        }
        if(!empty(ob_get_contents())) ob_end_clean ();
        ob_start();
        include $path;
        $content = ob_get_contents();
        ob_end_clean();
        $this->response->end($content);
    }

    /**
     * 启用Http GZIP压缩
     * $level 压缩等级,范围是1-9
     */
    final public function gzip($level = NULL  ){
        if($level === NULL ){
            $level = Config::get_instance ()->get('app.gzip',0);
        }
        $level>0 && $this->response->gzip( $level);
    }

    public function __set($name,$object){
        $this->$name = $object;
    }

    public function __get($name){
        return $this->$name;
    }

}

接下来创建frame/Lib/WsController.php,代码如下

<?php
/**
 * Websocket Controller
 */
namespace Piz;
class WSController
{
    /**
     * @var \Piz\Router
     */
    protected $router;
    /**
     * @var swoole_server
     */
    protected $server;
    /**
     * @var swoole_server->frame
     */
    protected $frame;
    /**
     * @var swoole_server->task
     */
    protected $task;

    public function __set($name,$object){
        $this->$name = $object;
    }

    public function __get($name){
        return $this->$name;
    }
}

怎么样,是不是很简单。。。

接下来,我要在App.php上做个限制,目的是为了防止http业务继承了websocket的控制器,同样也怕这个问题在websocket业务上出现,怎么办呢,一,强制所有的项目控制器必须继续小框架的控制器,第二,在App.php上检查项目控制器的继承类名称。
代码修改方法也简单,用到了一个php自带的方法 get_parent_class ,用它来检查是否继承自指定的类。

App->http增加以下代码

if(get_parent_class ($class)!='Piz\Controller'){
                    $response->header('Content-type',"text/html;charset=utf-8;");
                    $response->status(503);
                    $response->end('503 Service Unavailable');
                    echo "[{$classname}]  必须继承 Piz\Controller",PHP_EOL;
                    return ;
                }

App->websocket增加以下代码

if(get_parent_class ($class)!='Piz\WsController'){
                    echo "[{$classname}]  必须继承 Piz\WsController",PHP_EOL;
                    return ;
                }

App.php代码请移步码云 https://gitee.com/pizzzz/piz/blob/master/frame/Lib/App.php

接下来就是修改app/modules下各模块控制器的继承类了,小伙伴们自己改吧。。我就不贴代码了。

下一篇,Log不能少

点赞