app模式重构

This commit is contained in:
thinkphp
2015-09-26 20:45:09 +08:00
parent cb9faf2aa9
commit e58fa93b59
7 changed files with 210 additions and 279 deletions

View File

@@ -23,8 +23,11 @@ class App {
* @access public
* @return void
*/
static public function run($config) {
static public function run(array $config=[]) {
if(version_compare(PHP_VERSION,'5.4.0','<')) {
throw new Exception('require PHP > 5.4.0 !');
}
// 日志初始化
Log::init($config['log']);
@@ -43,12 +46,10 @@ class App {
Hook::listen('app_init');
// 初始化公共模块
define('COMMON_PATH', APP_PATH . $config['common_module'].'/');
self::initModule(COMMON_PATH,$config);
self::initModule(APP_PATH . $config['common_module'].'/',$config);
// 启动session
if(!IS_CLI) {
if($config['use_session']) {
Session::init($config['session']);
}
@@ -67,7 +68,7 @@ class App {
$namespace = MODULE_NAME.'\\'.CONTROLLER_LAYER.'\\'.CONTROLLER_NAME.'\\';
}else{
// 空控制器
$namespace = MODULE_NAME.'\\'.CONTROLLER_LAYER.'\\empty\\';
$namespace = MODULE_NAME.'\\'.CONTROLLER_LAYER.'\\empty\\';
}
$actionName = strtolower(ACTION_NAME);
if(class_exists($namespace.$actionName)){
@@ -133,11 +134,9 @@ class App {
$data = $method->invoke($instance);
}
// 操作方法执行完成监听
Hook::listen('action_end', $call);
if(IS_API){
// API接口返回数据
self::returnData($data,$config['default_ajax_return']);
}
Hook::listen('action_end', $data);
// 返回数据
Response::returnData($data,$config['default_return_type']);
}else{
// 操作方法不是Public 抛出异常
throw new \ReflectionException();
@@ -151,49 +150,9 @@ class App {
throw new Exception('[ ' . (new \ReflectionClass($instance))->getName() . ':' . $action . ' ] not exists ', 404);
}
}
// 监听app_end
Hook::listen('app_end');
return ;
}
/**
* 返回API数据到客户端
* @access protected
* @param mixed $data 要返回的数据
* @param String $type 返回数据格式
* @return void
*/
static public function returnData($data, $type='') {
$headers = [
'json' => 'application/json',
'xml' => 'text/xml',
'jsonp' => 'application/javascript',
'script'=> 'application/javascript',
'text' => 'text/plain',
];
$type = strtolower($type);
if(isset($headers[$type])){
header('Content-Type:'.$headers[$type].'; charset=utf-8');
}
switch ($type){
case 'json':
// 返回JSON数据格式到客户端 包含状态信息
$data = Transform::jsonEncode($data);
break;
case 'xml':
// 返回xml格式数据
$data = Transform::xmlEncode($data);
break;
case 'jsonp':
// 返回JSON数据格式到客户端 包含状态信息
$handler = isset($_GET[Config::get('var_jsonp_handler')]) ? $_GET[Config::get('var_jsonp_handler')] : Config::get('default_jsonp_handler');
$data = $handler . '(' . Transform::jsonEncode($data) . ');';
break;
}
exit($data);
}
/**
* 初始化模块
* @access private
@@ -297,9 +256,6 @@ class App {
$_SERVER['PATH_INFO'] = preg_replace($config['url_html_suffix']? '/\.('.trim($config['url_html_suffix'],'.').')$/i' : '/\.'.__EXT__.'$/i', '', $_SERVER['PATH_INFO']);
}
// URL常量
define('__SELF__',strip_tags($_SERVER[$config['url_request_uri']]));
// 获取模块名称
define('MODULE_NAME', defined('BIND_MODULE')? BIND_MODULE : self::getModule($config));

View File

@@ -15,23 +15,29 @@ use org\Transform;
class Controller {
// 视图类实例
protected $view = null;
protected $view = null;
protected $config = [
'before_action_list' = [],
'success_tmpl' = '',
'error_tmpl' = '',
];
/**
* 架构函数 初始化视图类 并采用内置模板引擎
* @access public
*/
public function __construct(){
public function __construct($config=[]){
// 模板引擎参数
$this->view = new View();
$this->view = new View();
$this->config(empty($config)? Config::get() : $config);
// 控制器初始化
if(method_exists($this, '_initialize')){
$this->_initialize();
}
// 前置操作方法
// 支持 ['action1','action2'] 或者 ['action1'=>['only'=>'index'],'action2'=>'except'=>'login']
$list = Config::get('before_action_list');
$list = $this->config['before_action_list'];
if($list){
foreach($list as $method=>$options){
is_numeric($method)?
@@ -41,6 +47,23 @@ class Controller {
}
}
/**
* 设置控制器参数
* @access public
* @param array $config 视图参数
* @return View
*/
public function config($config=[]){
if(is_array($config)){
foreach($this->config as $key=>$val){
if(isset($config[$key])){
$this->config[$key] = $config[$key];
}
}
return $this;
}
}
/**
* 前置操作
* @access protected
@@ -71,8 +94,8 @@ class Controller {
* @param string $cache_id 模板缓存标识
* @return mixed
*/
public function display($template = '', $vars = [], $cache_id = ''){
$this->view->display($template, $vars, $cache_id);
public function fetch($template = '', $vars = [], $cache_id = ''){
return $this->view->fetch($template, $vars, $cache_id);
}
/**
@@ -83,7 +106,7 @@ class Controller {
* @return mixed
*/
public function show($content, $vars = []){
$this->view->http('http_render_content', true)->display($content, $vars);
return $this->view->fetch($content, $vars,'',true);
}
/**
@@ -97,27 +120,6 @@ class Controller {
$this->view->assign($name, $value);
}
public function __set($name, $value){
return $this->assign($name, $value);
}
/**
* 返回API数据到客户端
* @access protected
* @param mixed $data 要返回的数据
* @param integer $code 返回的code
* @param mixed $msg 提示信息
* @param string $type 返回数据格式
* @return void
*/
protected function result($data,$code=0,$msg='',$type='') {
$result['code'] = $code;
$result['msg'] = $msg;
$result['time'] = NOW_TIME;
$result['data'] = $data;
App::returnData($result,$type);
}
/**
* Ajax方式返回数据到客户端
* @access protected
@@ -126,19 +128,7 @@ class Controller {
* @return void
*/
protected function ajaxReturn($data, $type='') {
App::returnData($data,$type);
}
/**
* Action跳转(URL重定向 支持指定模块和延时跳转
* @access protected
* @param string $url 跳转的URL表达式
* @param array $params 其它URL参数
* @return void
*/
protected function redirect($url,$params=[]) {
$url = U($url,$params);
header('Location: ' . $url);
Response::returnData($data,$type);
}
/**
@@ -150,7 +140,7 @@ class Controller {
* @return void
*/
protected function error($message, $jumpUrl = '', $ajax = false) {
$this->dispatchJump($message, 0, $jumpUrl, $ajax);
return $this->dispatchJump($message, 0, $jumpUrl, $ajax);
}
/**
@@ -162,7 +152,7 @@ class Controller {
* @return void
*/
protected function success($message, $jumpUrl = '', $ajax = false) {
$this->dispatchJump($message, 1, $jumpUrl, $ajax);
return $this->dispatchJump($message, 1, $jumpUrl, $ajax);
}
/**
@@ -204,7 +194,7 @@ class Controller {
// 默认操作成功自动返回操作前页面
if(!$jumpUrl)
$data["jumpUrl"] = $_SERVER["HTTP_REFERER"];
$this->display(Config::get('success_tmpl'),$data);
return $this->display(Config::get('success_tmpl'),$data);
}else{
$data['error'] = $message;// 提示信息
//发生错误时候默认停留3秒
@@ -212,9 +202,7 @@ class Controller {
// 默认发生错误的话自动返回上页
if(!$jumpUrl)
$data['jumpUrl'] = 'javascript:history.back(-1);';
$this->display(Config::get('error_tmpl'),$data);
// 中止执行 避免出错后继续执行
exit ;
return $this->display(Config::get('error_tmpl'),$data);
}
}
}

View File

@@ -72,20 +72,6 @@ abstract class rest {
}
}
/**
* 设置页面输出的CONTENT_TYPE和编码
* @access public
* @param string $type content_type 类型对应的扩展名
* @param string $charset 页面输出编码
* @return void
*/
public function setContentType($type, $charset='utf-8'){
if(headers_sent()) return;
$type = strtolower($type);
if(isset($this->restOutputType[$type])) //过滤content_type
header('Content-Type: '.$this->restOutputType[$type].'; charset='.$charset);
}
/**
* 输出返回数据
* @access protected
@@ -95,96 +81,15 @@ abstract class rest {
* @return void
*/
protected function response($data,$type='',$code=200) {
$this->sendHttpStatus($code);
exit($this->encodeData($data,strtolower($type)));
}
/**
* 编码数据
* @access protected
* @param mixed $data 要返回的数据
* @param String $type 返回类型 JSON XML
* @return void
*/
protected function encodeData($data,$type='') {
if(empty($data)) return '';
if('json' == $type) {
// 返回JSON数据格式到客户端 包含状态信息
$data = json_encode($data, JSON_UNESCAPED_UNICODE);
}elseif('xml' == $type){
// 返回xml格式数据
$data = xml_encode($data);
}elseif('php'==$type){
$data = serialize($data);
}// 默认直接输出
$this->setContentType($type);
header('Content-Length: ' . strlen($data));
return $data;
}
// 发送Http状态信息
protected function sendHttpStatus($status) {
static $_status = [
// Informational 1xx
100 => 'Continue',
101 => 'Switching Protocols',
// Success 2xx
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
// Redirection 3xx
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Moved Temporarily ', // 1.1
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
// 306 is deprecated but reserved
307 => 'Temporary Redirect',
// Client Error 4xx
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',
// Server Error 5xx
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
509 => 'Bandwidth Limit Exceeded'
];
if(isset($_status[$code])) {
header('HTTP/1.1 '.$code.' '.$_status[$code]);
// 确保FastCGI模式下正常
header('Status:'.$code.' '.$_status[$code]);
}
Response::sendHttpStatus($code);
Response::returnData($data,strtolower($type)));
}
/**
* 获取当前请求的Accept头信息
* @return string
*/
protected function getAcceptType(){
static public function getAcceptType(){
$type = [
'html' => 'text/html,application/xhtml+xml,*/*',
'xml' => 'application/xml,text/xml,application/x-xml',

View File

@@ -1082,7 +1082,7 @@ abstract class Driver {
$_config['hostport'] = explode(',',$this->config['hostport']);
$_config['database'] = explode(',',$this->config['database']);
$_config['dsn'] = explode(',',$this->config['dsn']);
$_config['charset'] = explode(',',$this->config['charset']);
$_config['charset'] = explode(',',$this->config['charset']);
$m = floor(mt_rand(0,$this->config['master_num']-1));
// 数据库读写是否分离

View File

@@ -46,7 +46,7 @@ class Error {
switch ($errno) {
case E_USER_ERROR:
Log::record($errorStr, 'ERROR');
self::halt($errorStr);
self::halt($errorStr,$errno);
break;
case E_STRICT:
case E_USER_WARNING:
@@ -81,11 +81,12 @@ class Error {
/**
* 错误输出
* @param mixed $error 错误
* @param int $errno 错误代码
* @return void
*/
static public function halt($error) {
static public function halt($error,$code=1) {
$message = is_array($error)? $error['message'] : $error;
$code = is_array($error)? $error['code'] : 1;
$code = is_array($error)? $error['code'] : $code;
if(IS_CLI){
exit($message);
}elseif(IS_API){

143
library/think/response.php Normal file
View File

@@ -0,0 +1,143 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace think;
use org\Transform;
class Response {
/**
* 返回数据到客户端
* @access protected
* @param mixed $data 要返回的数据
* @param String $type 返回数据格式
* @return void
*/
static public function returnData($data, $type='') {
$headers = [
'json' => 'application/json',
'xml' => 'text/xml',
'html' => 'text/html',
'jsonp' => 'application/javascript',
'script'=> 'application/javascript',
'text' => 'text/plain',
];
$type = strtolower($type);
if(isset($headers[$type])){
header('Content-Type:'.$headers[$type].'; charset=utf-8');
}
switch ($type){
case 'json':
// 返回JSON数据格式到客户端 包含状态信息
$data = Transform::jsonEncode($data);
break;
case 'xml':
// 返回xml格式数据
$data = Transform::xmlEncode($data);
break;
case 'jsonp':
// 返回JSON数据格式到客户端 包含状态信息
$handler = isset($_GET[Config::get('var_jsonp_handler')]) ? $_GET[Config::get('var_jsonp_handler')] : Config::get('default_jsonp_handler');
$data = $handler . '(' . Transform::jsonEncode($data) . ');';
break;
}
exit($data);
}
/**
* 返回封装后的API数据到客户端
* @access protected
* @param mixed $data 要返回的数据
* @param integer $code 返回的code
* @param mixed $msg 提示信息
* @param string $type 返回数据格式
* @return void
*/
static public function result($data,$code=0,$msg='',$type='') {
$result['code'] = $code;
$result['msg'] = $msg;
$result['time'] = NOW_TIME;
$result['data'] = $data;
self::returnData($result,$type);
}
/**
* URL重定向
* @access protected
* @param string $url 跳转的URL表达式
* @param array $params 其它URL参数
* @return void
*/
static public function redirect($url,$params=[]) {
$url = Url::build($url,$params);
header('Location: ' . $url);
}
// 发送Http状态信息
static public function sendHttpStatus($status) {
static $_status = [
// Informational 1xx
100 => 'Continue',
101 => 'Switching Protocols',
// Success 2xx
200 => 'OK',
201 => 'Created',
202 => 'Accepted',
203 => 'Non-Authoritative Information',
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
// Redirection 3xx
300 => 'Multiple Choices',
301 => 'Moved Permanently',
302 => 'Moved Temporarily ', // 1.1
303 => 'See Other',
304 => 'Not Modified',
305 => 'Use Proxy',
// 306 is deprecated but reserved
307 => 'Temporary Redirect',
// Client Error 4xx
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',
// Server Error 5xx
500 => 'Internal Server Error',
501 => 'Not Implemented',
502 => 'Bad Gateway',
503 => 'Service Unavailable',
504 => 'Gateway Timeout',
505 => 'HTTP Version Not Supported',
509 => 'Bandwidth Limit Exceeded'
];
if(isset($_status[$code])) {
header('HTTP/1.1 '.$code.' '.$_status[$code]);
// 确保FastCGI模式下正常
header('Status:'.$code.' '.$_status[$code]);
}
}
}

View File

@@ -16,11 +16,6 @@ class View {
protected $theme = ''; // 模板主题名称
protected $data = []; // 模板变量
protected $config = [ // 视图参数
'http_output_content' => true,
'http_content_type' => 'text/html',
'http_charset' => 'utf-8',
'http_cache_control' => 'private',
'http_render_content' => false,
'theme_on' => false,
'auto_detect_theme' => false,
'var_theme' => 't',
@@ -34,7 +29,7 @@ class View {
];
public function __construct(array $config = []){
$this->config = array_merge($this->config, empty($config)? (array)Config::get('view') : $config);
$this->config(empty($config)? Config::get() : $config);
$this->engine($this->config['engine_type']);
}
@@ -53,16 +48,6 @@ class View {
}
}
/**
* 视图参数设置
* @access public
* @param mixed $name
* @param mixed $value
*/
public function __set($name, $value = ''){
$this->config[$name] = $value;
}
/**
* 设置视图参数
* @access public
@@ -70,8 +55,14 @@ class View {
* @return View
*/
public function config(array $config=[]){
$this->config = array_merge($this->config, $config);
return $this;
if(is_array($config)){
foreach($this->config as $key=>$val){
if(isset($config[$key])){
$this->config[$key] = $config[$key];
}
}
return $this;
}
}
/**
@@ -106,38 +97,16 @@ class View {
return $this;
}
/**
* 加载模板和页面输出 可以返回输出内容
* @access public
* @param string $template 模板文件名
* @param array $vars 模板输出变量
* @param string $cache_id 模板缓存标识
* @return mixed
*/
public function display($template = '', $vars = [], $cache_id = '') {
Hook::listen('view_begin', $template);
// 解析并获取模板内容
$content = $this->fetch($template, $vars, $cache_id);
// 输出内容过滤
Hook::listen('view_filter', $content);
// 输出模板内容
if($this->config['http_output_content']) {
$this->render($content);
}else{ // 返回解析后的内容
return $content;
}
}
/**
* 解析和获取模板内容 用于输出
* @access protected
* @access public
* @param string $template 模板文件名或者内容
* @param array $vars 模板输出变量
* @param string $cache_id 模板缓存标识
* @return string
*/
protected function fetch($template, $vars = [], $cache_id='') {
if(!$this->config['http_render_content']) {
public function fetch($template, $vars = [], $cache_id='',$renderContent=false) {
if(!$renderContent){
// 获取模板文件名
$template = $this->parseTemplate($template);
// 模板不存在 抛出异常
@@ -170,7 +139,7 @@ class View {
return $template;
}
$depr = $this->config['view_depr'];
$template = str_replace(':', $depr, $template);
$template = str_replace(':', $depr, $template);
// 获取当前模块
$module = MODULE_NAME;
@@ -237,35 +206,4 @@ class View {
return $tmplPath.$theme;
}
/**
* 视图输出参数设置
* @access public
* @param mixed $config
* @param mixed $value
*/
public function http($config = [], $value = ''){
if(is_array($config)) {
$this->config = array_merge($this->config, $config);
}else{
$this->config[$config] = $value;
}
return $this;
}
/**
* 输出内容文本可以包括Html
* @access private
* @param string $content 输出内容
* @param string $charset 模板输出字符集
* @param string $contentType 输出类型
* @return mixed
*/
private function render($content){
// 网页字符编码
header('Content-Type:' . $this->config['http_content_type'] . '; charset=' . $this->config['http_charset']);
header('Cache-control:' . $this->config['http_cache_control']); // 页面缓存控制
header('X-Powered-By:ThinkPHP');
// 输出模板文件
echo $content;
}
}