小框架里处理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不能少
热门评论
而且你在控制器基类中用obstart等操作,app中调用方法时还是obstart操作。。你在控制器积累中用response->end输出,app中后边还有个response_end,这样swoole就会抛出request已经结束的异常
这控制器基类的私有属性貌似都应该在app中赋值吧?
protected $router;
这个私有变量没赋值吧??