内核更新升级

This commit is contained in:
2016-06-27 17:49:19 +08:00
parent f9c34a87f1
commit 56fd9ee760
19 changed files with 563 additions and 584 deletions

View File

@@ -31,9 +31,32 @@ defined('CONF_PATH') or define('CONF_PATH', APP_PATH); // 配置文件目录
defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件后缀
defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 环境变量的配置前缀
defined('IS_API') or define('IS_API', false); // 是否API接口
defined('APP_AUTO_RUN') or define('APP_AUTO_RUN', true); // 是否自动运行
defined('AUTO_SCAN_PACKAGE') or define('AUTO_SCAN_PACKAGE', false); // 是否自动扫描非Composer安装类库
// 环境常量
define('IS_CLI', PHP_SAPI == 'cli' ? true : false);
define('IS_WIN', strstr(PHP_OS, 'WIN') ? true : false);
// 载入Loader类
require CORE_PATH . 'Loader.php';
// 加载环境变量配置文件
if (is_file(ROOT_PATH . 'env' . EXT)) {
$env = include ROOT_PATH . 'env' . EXT;
foreach ($env as $key => $val) {
$name = ENV_PREFIX . $key;
if (is_bool($val)) {
$val = $val ? 1 : 0;
}
putenv("$name=$val");
}
}
// 注册自动加载
\think\Loader::register();
// 注册错误和异常处理机制
\think\Error::register();
// 加载模式配置文件
\think\Config::set(include THINK_PATH . 'convention' . EXT);

View File

@@ -29,8 +29,8 @@ use think\View;
/**
* 快速导入Traits PHP5.5以上无需调用
* @param string $class trait库
* @param string $ext 类库后缀
* @param string $class trait库
* @param string $ext 类库后缀
* @return boolean
*/
function load_trait($class, $ext = EXT)
@@ -41,9 +41,9 @@ function load_trait($class, $ext = EXT)
/**
* 抛出异常处理
*
* @param string $msg 异常消息
* @param integer $code 异常代码 默认为0
* @param string $exception 异常类
* @param string $msg 异常消息
* @param integer $code 异常代码 默认为0
* @param string $exception 异常类
*
* @throws Exception
*/
@@ -55,9 +55,9 @@ function exception($msg, $code = 0, $exception = '')
/**
* 记录时间(微秒)和内存使用情况
* @param string $start 开始标签
* @param string $end 结束标签
* @param integer|string $dec 小数位 如果是m 表示统计内存占用
* @param string $start 开始标签
* @param string $end 结束标签
* @param integer|string $dec 小数位 如果是m 表示统计内存占用
* @return mixed
*/
function debug($start, $end = '', $dec = 6)
@@ -71,9 +71,9 @@ function debug($start, $end = '', $dec = 6)
/**
* 获取语言变量值
* @param string $name 语言变量名
* @param array $vars 动态变量值
* @param string $lang 语言
* @param string $name 语言变量名
* @param array $vars 动态变量值
* @param string $lang 语言
* @return mixed
*/
function lang($name, $vars = [], $lang = '')
@@ -83,9 +83,9 @@ function lang($name, $vars = [], $lang = '')
/**
* 获取和设置配置参数
* @param string|array $name 参数名
* @param mixed $value 参数值
* @param string $range 作用域
* @param string|array $name 参数名
* @param mixed $value 参数值
* @param string $range 作用域
* @return mixed
*/
function config($name = '', $value = null, $range = '')
@@ -99,10 +99,9 @@ function config($name = '', $value = null, $range = '')
/**
* 获取输入数据 支持默认值和过滤
* @param string $key 获取的变量名
* @param mixed $default 默认值
* @param string $filter 过滤方法
* @param bool $merge 是否合并系统默认过滤方法
* @param string $key 获取的变量名
* @param mixed $default 默认值
* @param string $filter 过滤方法
* @return mixed
*/
function input($key, $default = null, $filter = null)
@@ -123,17 +122,17 @@ function input($key, $default = null, $filter = null)
// 默认为自动判断
$method = 'param';
}
if(isset($has)){
if (isset($has)) {
return request()->has($key, $method, $default);
}else{
} else {
return request()->$method($key, $default, $filter);
}
}
/**
* 渲染输出Widget
* @param string $name Widget名称
* @param array $data 传人的参数
* @param string $name Widget名称
* @param array $data 传人的参数
* @return mixed
*/
function widget($name, $data = [])
@@ -143,9 +142,9 @@ function widget($name, $data = [])
/**
* 实例化Model
* @param string $name Model名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @param string $name Model名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Model
*/
function model($name = '', $layer = 'model', $appendSuffix = false)
@@ -155,9 +154,9 @@ function model($name = '', $layer = 'model', $appendSuffix = false)
/**
* 实例化验证器
* @param string $name 验证器名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @param string $name 验证器名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Validate
*/
function validate($name = '', $layer = 'validate', $appendSuffix = false)
@@ -167,8 +166,8 @@ function validate($name = '', $layer = 'validate', $appendSuffix = false)
/**
* 实例化数据库类
* @param string $name 操作的数据表名称(不含前缀)
* @param array|string $config 数据库配置参数
* @param string $name 操作的数据表名称(不含前缀)
* @param array|string $config 数据库配置参数
* @return \think\db\Query
*/
function db($name = '', $config = [])
@@ -178,9 +177,9 @@ function db($name = '', $config = [])
/**
* 实例化控制器 格式:[模块/]控制器
* @param string $name 资源地址
* @param string $layer 控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @param string $name 资源地址
* @param string $layer 控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Controller
*/
function controller($name, $layer = 'controller', $appendSuffix = false)
@@ -190,10 +189,10 @@ function controller($name, $layer = 'controller', $appendSuffix = false)
/**
* 调用模块的操作方法 参数格式 [模块/控制器/]操作
* @param string $url 调用地址
* @param string|array $vars 调用参数 支持字符串和数组
* @param string $layer 要调用的控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @param string $url 调用地址
* @param string|array $vars 调用参数 支持字符串和数组
* @param string $layer 要调用的控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return mixed
*/
function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
@@ -203,9 +202,9 @@ function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
/**
* 导入所需的类库 同java的Import 本函数有缓存功能
* @param string $class 类库命名空间字符串
* @param string $baseUrl 起始路径
* @param string $ext 导入的文件扩展名
* @param string $class 类库命名空间字符串
* @param string $baseUrl 起始路径
* @param string $ext 导入的文件扩展名
* @return boolean
*/
function import($class, $baseUrl = '', $ext = EXT)
@@ -215,8 +214,8 @@ function import($class, $baseUrl = '', $ext = EXT)
/**
* 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面
* @param string $class 类库
* @param string $ext 类库后缀
* @param string $class 类库
* @param string $ext 类库后缀
* @return boolean
*/
function vendor($class, $ext = EXT)
@@ -226,9 +225,9 @@ function vendor($class, $ext = EXT)
/**
* 浏览器友好的变量输出
* @param mixed $var 变量
* @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串
* @param string $label 标签 默认为空
* @param mixed $var 变量
* @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串
* @param string $label 标签 默认为空
* @return void|string
*/
function dump($var, $echo = true, $label = null)
@@ -238,10 +237,10 @@ function dump($var, $echo = true, $label = null)
/**
* Url生成
* @param string $url 路由地址
* @param string|array $value 变量
* @param bool|string $suffix 前缀
* @param bool|string $domain 域名
* @param string $url 路由地址
* @param string|array $value 变量
* @param bool|string $suffix 前缀
* @param bool|string $domain 域名
* @return string
*/
function url($url = '', $vars = '', $suffix = true, $domain = false)
@@ -251,9 +250,9 @@ function url($url = '', $vars = '', $suffix = true, $domain = false)
/**
* Session管理
* @param string|array $name session名称如果为数组表示进行session设置
* @param mixed $value session值
* @param string $prefix 前缀
* @param string|array $name session名称如果为数组表示进行session设置
* @param mixed $value session值
* @param string $prefix 前缀
* @return mixed
*/
function session($name, $value = '', $prefix = null)
@@ -278,9 +277,9 @@ function session($name, $value = '', $prefix = null)
/**
* Cookie管理
* @param string|array $name cookie名称如果为数组表示进行cookie设置
* @param mixed $value cookie值
* @param mixed $option 参数
* @param string|array $name cookie名称如果为数组表示进行cookie设置
* @param mixed $value cookie值
* @param mixed $option 参数
* @return mixed
*/
function cookie($name, $value = '', $option = null)
@@ -305,9 +304,9 @@ function cookie($name, $value = '', $option = null)
/**
* 缓存管理
* @param mixed $name 缓存名称,如果为数组表示进行缓存设置
* @param mixed $value 缓存值
* @param mixed $options 缓存参数
* @param mixed $name 缓存名称,如果为数组表示进行缓存设置
* @param mixed $value 缓存值
* @param mixed $options 缓存参数
* @return mixed
*/
function cache($name, $value = '', $options = null)
@@ -338,8 +337,8 @@ function cache($name, $value = '', $options = null)
/**
* 记录日志信息
* @param mixed $log log信息 支持字符串和数组
* @param string $level 日志级别
* @param mixed $log log信息 支持字符串和数组
* @param string $level 日志级别
* @return void|array
*/
function trace($log = '[think]', $level = 'log')
@@ -375,9 +374,9 @@ function response($data = [], $code = 200, $header = [], $type = 'html')
/**
* 渲染模板输出
* @param string $template 模板文件
* @param array $vars 模板变量
* @param integer $code 状态码
* @param string $template 模板文件
* @param array $vars 模板变量
* @param integer $code 状态码
* @return \think\response\View
*/
function view($template = '', $vars = [], $code = 200)
@@ -426,9 +425,9 @@ function xml($data = [], $code = 200, $header = [], $options = [])
/**
* 获取\think\response\Redirect对象实例
* @param mixed $url 重定向地址 支持Url::build方法的地址
* @param mixed $url 重定向地址 支持Url::build方法的地址
* @param array|integer $params 额外参数
* @param integer $code 状态码
* @param integer $code 状态码
* @return \think\response\Redirect
*/
function redirect($url = [], $params = [], $code = 302)
@@ -442,9 +441,9 @@ function redirect($url = [], $params = [], $code = 302)
/**
* 抛出HTTP异常
* @param integer $code 状态码
* @param string $message 错误信息
* @param array $header 参数
* @param integer $code 状态码
* @param string $message 错误信息
* @param array $header 参数
*/
function abort($code, $message = null, $header = [])
{

View File

@@ -41,29 +41,31 @@ class App
/**
* @var bool 应用调试模式
*/
*/
public static $debug = true;
/**
* @var string 应用类库命名空间
*/
*/
public static $namespace = 'app';
/**
* @var bool 应用类库后缀
*/
*/
public static $suffix = false;
/**
* @var bool 应用路由检测
*/
*/
protected static $routeCheck;
/**
* @var bool 严格路由检测
*/
*/
protected static $routeMust;
protected static $dispatch;
/**
* 执行应用程序
* @access public
@@ -90,12 +92,14 @@ class App
}
}
// 获取当前请求的调度信息
$dispatch = $request->dispatch();
// 获取应用调度信息
$dispatch = self::$dispatch;
if (empty($dispatch)) {
// 未指定调度类型 则进行URL路由检测
// 进行URL路由检测
$dispatch = self::routeCheck($request, $config);
}
// 记录当前调度信息
$request->dispatch($dispatch);
// 记录路由信息
self::$debug && Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
// 监听app_begin
@@ -108,7 +112,7 @@ class App
break;
case 'module':
// 模块/控制器/操作
$data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null );
$data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null);
break;
case 'controller':
// 执行控制器操作
@@ -136,11 +140,11 @@ class App
Hook::listen('app_end', $data);
// 清空类的实例化
Loader::clearInstance();
// 输出数据到客户端
if ($data instanceof Response) {
return $data;
} elseif(!is_null($data)) {
} elseif (!is_null($data)) {
// 默认自动识别响应输出类型
$isAjax = $request->isAjax();
$type = $isAjax ? Config::get('default_ajax_return') : Config::get('default_return_type');
@@ -150,6 +154,19 @@ class App
}
}
/**
* 设置当前请求的调度信息
* @access public
* @param array|string $dispatch 调度信息
* @param string $type 调度类型
* @param array $params 参数
* @return void
*/
public static function dispatch($dispath, $type = 'module', $params = [])
{
self::$dispatch = ['type' => $type, $type => $dispatch, 'params' => $params];
}
/**
* 执行函数或者闭包方法 支持参数调用
* @access public
@@ -222,7 +239,7 @@ class App
}
}
// 全局过滤
array_walk_recursive($args, [Request::instance(),'filterExp']);
array_walk_recursive($args, [Request::instance(), 'filterExp']);
}
return $args;
}
@@ -240,10 +257,11 @@ class App
if (is_string($result)) {
$result = explode('/', $result);
}
$request = Request::instance();
if ($config['app_multi_module']) {
// 多模块部署
$module = strip_tags(strtolower($result[0] ?: $config['default_module']));
$bind = Route::bind('module');
$bind = Route::getBind('module');
$available = false;
if ($bind) {
// 绑定模块
@@ -258,6 +276,7 @@ class App
// 模块初始化
if ($module && $available) {
// 初始化模块
$request->module($module);
$config = self::init($module);
} else {
throw new HttpException(404, 'module not exists:' . $module);
@@ -265,12 +284,13 @@ class App
} else {
// 单一模块部署
$module = '';
$request->module($module);
}
// 当前模块路径
App::$modulePath = APP_PATH . ($module ? $module . DS : '');
// 是否自动转换控制器和操作名
$convert = is_bool($convert) ? $convert : $config['url_convert'];
$convert = is_bool($convert) ? $convert : $config['url_convert'];
// 获取控制器名
$controller = strip_tags($result[1] ?: $config['default_controller']);
$controller = $convert ? strtolower($controller) : $controller;
@@ -279,15 +299,8 @@ class App
$actionName = strip_tags($result[2] ?: $config['default_action']);
$actionName = $convert ? strtolower($actionName) : $actionName;
// 执行操作
if (!preg_match('/^[A-Za-z](\/|\.|\w)*$/', $controller)) {
// 安全检测
throw new \InvalidArgumentException('illegal controller name:' . $controller);
}
// 设置当前请求的模块、控制器、操作
$request = Request::instance();
$request->module($module)->controller($controller)->action($actionName);
// 设置当前请求的控制器、操作
$request->controller($controller)->action($actionName);
// 监听module_init
Hook::listen('module_init', $request);
@@ -327,17 +340,17 @@ class App
{
if (empty(self::$init)) {
// 初始化应用
$config = self::init();
self::$suffix = $config['class_suffix'];
$config = self::init();
self::$suffix = $config['class_suffix'];
// 应用调试模式
self::$debug = Config::get('app_debug');
self::$debug = Config::get('app_debug');
if (!self::$debug) {
ini_set('display_errors', 'Off');
}
// 应用命名空间
self::$namespace = $config['app_namespace'];
self::$namespace = $config['app_namespace'];
Loader::addNamespace($config['app_namespace'], APP_PATH);
if (!empty($config['root_namespace'])) {
Loader::addNamespace($config['root_namespace']);
@@ -364,7 +377,6 @@ class App
return self::$init;
}
/**
* 初始化应用或模块
* @access public
@@ -399,7 +411,7 @@ class App
// 加载别名文件
if (is_file(CONF_PATH . $module . 'alias' . EXT)) {
Loader::addMap(include CONF_PATH . $module . 'alias' . EXT);
Loader::addClassMap(include CONF_PATH . $module . 'alias' . EXT);
}
// 加载行为扩展文件
@@ -432,14 +444,14 @@ class App
{
// 检测URL禁用后缀
if ($config['url_deny_suffix'] && preg_match('/\.(' . $config['url_deny_suffix'] . ')$/i', $request->pathinfo())) {
throw new Exception('url suffix deny:'.$request->ext());
throw new Exception('url suffix deny:' . $request->ext());
}
$path = $request->path();
$depr = $config['pathinfo_depr'];
$result = false;
// 路由检测
$check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
$check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
if ($check) {
// 开启路由
if (!empty($config['route'])) {
@@ -456,11 +468,9 @@ class App
}
if (false === $result) {
// 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索
$result = Route::parseUrl($path, $depr, $config['controller_auto_search'], $config['url_param_type']);
$result = Route::parseUrl($path, $depr, $config['controller_auto_search']);
}
// 注册调度机制
return $request->dispatch($result);
return $result;
}
/**

View File

@@ -102,7 +102,7 @@ class Lang
public static function has($name, $range = '')
{
$range = $range ?: self::$range;
return isset(self::$lang[$range][strtolower($name)]);
return isset(self::$lang[$range][strtolower($name)]);
}
/**
@@ -169,7 +169,7 @@ class Lang
}
if (empty(self::$allowLangList) || in_array($langSet, self::$allowLangList)) {
// 合法的语言
self::$range = $langSet;
self::$range = $langSet ?: self::$range;
}
return self::$range;
}

View File

@@ -59,34 +59,38 @@ class Loader
if (!strpos($class, '\\')) {
return false;
}
// 解析命名空间
list($name, $class) = explode('\\', $class, 2);
if (isset(self::$namespace[$name])) {
// 根命名空间
$path = self::$namespace[$name];
} elseif (is_dir(EXTEND_PATH . $name)) {
$item = explode('\\', $class);
// 解析命名空间所在的路径
if (count($item) > 2 && isset(self::$namespace[$item[0] . '\\' . $item[1]])) {
// 子命名空间定义(仅支持二级)
list($ns1, $ns2, $class) = explode('\\', $class, 3);
$path = self::$namespace[$ns1 . '\\' . $ns2];
} elseif (isset(self::$namespace[$item[0]])) {
// 根命名空间定义
list($name, $class) = explode('\\', $class, 2);
$path = self::$namespace[$name];
} elseif (is_dir(EXTEND_PATH . $item[0])) {
// 扩展类库命名空间
$path = EXTEND_PATH . $name . DS;
list($name, $class) = explode('\\', $class, 2);
$path = EXTEND_PATH . $name . DS;
} else {
// 非根命名空间检测
foreach (self::$namespace as $ns => $val) {
if (strpos($ns, '\\') && 0 === strpos($name . '\\' . $class, $ns)) {
$path = $val;
$class = substr($name . $class, strlen($ns));
break;
return false;
}
// 定位文件
$match = false;
foreach ((array) $path as $p) {
$filename = $p . str_replace('\\', DS, $class) . EXT;
if (is_file($filename)) {
// Win环境严格区分大小写
if (IS_WIN && false === strpos(realpath($filename), $class . EXT)) {
continue;
}
}
if (!isset($path)) {
return false;
$match = true;
break;
}
}
$filename = $path . str_replace('\\', DS, $class) . EXT;
if (is_file($filename)) {
// 开启调试模式Win环境严格区分大小写
if (IS_WIN && false === strpos(realpath($filename), $class . EXT)) {
return false;
}
if ($match) {
include $filename;
} else {
return false;
@@ -96,7 +100,7 @@ class Loader
}
// 注册classmap
public static function addMap($class, $map = '')
public static function addClassMap($class, $map = '')
{
if (is_array($class)) {
self::$map = array_merge(self::$map, $class);
@@ -119,7 +123,7 @@ class Loader
public static function addNamespaceAlias($namespace, $original = '')
{
if (is_array($namespace)) {
self::$namespaceAlias = array_merge(self::$namespace, $namespace);
self::$namespaceAlias = array_merge(self::$namespaceAlias, $namespace);
} else {
self::$namespaceAlias[$namespace] = $original;
}
@@ -130,83 +134,33 @@ class Loader
{
// 注册系统自动加载
spl_autoload_register($autoload ?: 'think\\Loader::autoload');
// 注册命名空间定义
self::addNamespace([
'think' => LIB_PATH . 'think' . DS,
'behavior' => LIB_PATH . 'behavior' . DS,
'traits' => LIB_PATH . 'traits' . DS,
]);
// 加载类库映射文件
self::addClassMap(include THINK_PATH . 'classmap' . EXT);
// Composer自动加载支持
if (is_dir(VENDOR_PATH . 'composer')) {
// 注册Composer自动加载
self::registerComposerLoader();
self::$composerLoader = true;
self::registerComposerLoader();
} elseif (is_file(VENDOR_PATH . 'think_autoload.php')) {
// 读取Composer自动加载文件
$autoload = include VENDOR_PATH . 'think_autoload.php';
if (is_array($autoload)) {
self::addMap($autoload);
}
} elseif (AUTO_SCAN_PACKAGE) {
if (is_file(RUNTIME_PATH . 'class_namespace.php')) {
self::addNamespace(include RUNTIME_PATH . 'class_namespace.php');
if (is_file(RUNTIME_PATH . 'load_files.php')) {
$files = include RUNTIME_PATH . 'load_files.php';
foreach ($files as $file) {
include $file;
}
}
} elseif (is_dir(VENDOR_PATH)) {
self::scanComposerPackage(VENDOR_PATH);
}
}
}
// 扫描composer package
private static function scanComposerPackage($path)
{
// 自动扫描下载Composer安装类库
$dirs = scandir($path, 1);
$namespace = [];
foreach ($dirs as $dir) {
if ('.' != $dir && '..' != $dir && is_file($path . $dir . DS . 'composer.json')) {
// 解析 package的composer.json 文件
$namespace = array_merge($namespace, self::parseComposerPackage($path . $dir . DS));
}
}
if (!empty($namespace)) {
self::addNamespace($namespace);
// 生成缓存
file_put_contents(RUNTIME_PATH . 'class_namespace.php', "<?php\nreturn " . var_export($namespace, true) . ';');
}
if (!empty(self::$load)) {
// 生成缓存
file_put_contents(RUNTIME_PATH . 'load_files.php', "<?php\nreturn " . var_export(self::$load, true) . ';');
}
}
// 解析Composer Package
private static function parseComposerPackage($package)
{
$content = file_get_contents($package . 'composer.json');
$result = json_decode($content, true);
$namespace = [];
if (!empty($result['autoload'])) {
$autoload = $result['autoload'];
if (isset($autoload['psr-0'])) {
foreach ($autoload['psr-0'] as $ns => $path) {
$namespace[rtrim($ns, '\\')] = realpath($package . $path . DS . str_replace('\\', DS, $ns)) . DS;
}
}
if (isset($autoload['psr-4'])) {
foreach ($autoload['psr-4'] as $ns => $path) {
$namespace[rtrim($ns, '\\')] = realpath($package . $path) . DS;
}
}
if (isset($autoload['files'])) {
// 命名空间和类库映射注册
self::addNamespace($autoload['namespace']);
self::addClassMap($autoload['classmap']);
// 载入composer包的文件列表
foreach ($autoload['files'] as $file) {
self::$load[] = realpath($package . $file);
require $package . $file;
include $file;
}
}
}
return $namespace;
}
// 注册composer自动加载
@@ -234,7 +188,7 @@ class Loader
if (is_file(VENDOR_PATH . 'composer/autoload_classmap.php')) {
$classMap = require VENDOR_PATH . 'composer/autoload_classmap.php';
if ($classMap) {
self::addMap($classMap);
self::addClassMap($classMap);
}
}

View File

@@ -164,10 +164,17 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
/**
* 获取关联模型实例
* @access protected
* @return Relation
* @param string|array $relation 关联查询
* @return Relation|Query
*/
protected function relation()
protected function relation($relation = null)
{
if (!is_null($relation)) {
// 执行关联查询
return $this->db->relation($relation);
}
// 获取关联对象实例
if (is_null($this->relation)) {
$this->relation = new Relation($this);
}
@@ -250,11 +257,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
list($type, $param) = explode(':', $type, 2);
}
switch ($type) {
case 'timestamp':
case 'datetime':
$format = !empty($param) ? $param : $this->dateFormat;
$value = date($format, $_SERVER['REQUEST_TIME']);
break;
case 'datetime':
case 'timestamp':
$value = $_SERVER['REQUEST_TIME'];
break;
}
@@ -549,6 +556,9 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 检测字段
if (!empty($this->field)) {
if (true === $this->field) {
$this->field = $this->db->getTableInfo('', 'fields');
}
foreach ($this->data as $key => $val) {
if (!in_array($key, $this->field)) {
unset($this->data[$key]);
@@ -666,7 +676,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
/**
* 设置允许写入的字段
* @access public
* @param bool $update
* @param bool|array $field 允许写入的字段 如果为true只允许写入数据表字段
* @return $this
*/
public function allowField($field)
@@ -971,25 +981,27 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
* 命名范围
* @access public
* @param string|array|Closure $name 命名范围名称 逗号分隔
* @param mixed $params 参数调用
* @param mixed ...$params 参数调用
* @return Model
*/
public static function scope($name, $params = [])
public static function scope($name)
{
$model = new static();
$query = $model->db();
if ($name instanceof \Closure) {
call_user_func_array($name, [ & $query, $params]);
} elseif ($name instanceof Query) {
if ($name instanceof Query) {
return $name;
} else {
if (is_string($name)) {
$names = explode(',', $name);
}
foreach ($names as $scope) {
}
$model = new static();
$params = func_get_args();
$params[0] = $model->db();
if ($name instanceof \Closure) {
call_user_func_array($name, $params);
} elseif (is_string($name)) {
$name = explode(',', $name);
}
if (is_array($name)) {
foreach ($name as $scope) {
$method = 'scope' . trim($scope);
if (method_exists($model, $method)) {
$model->$method($query, $params);
call_user_func_array([$model, $method], $params);
}
}
}

View File

@@ -109,6 +109,8 @@ class Request
'csv' => 'text/csv',
];
protected $content;
// 全局过滤规则
protected $filter;
// Hook扩展方法
@@ -126,6 +128,7 @@ class Request
$this->$name = $item;
}
}
$this->filter = Config::get('default_filter');
}
public function __call($method, $args)
@@ -177,9 +180,10 @@ class Request
* @param array $cookie
* @param array $files
* @param array $server
* @param string $content
* @return \think\Request
*/
public static function create($uri, $method = 'GET', $params = [], $cookie = [], $files = [], $server = [])
public static function create($uri, $method = 'GET', $params = [], $cookie = [], $files = [], $server = [], $content = null)
{
$server['PATH_INFO'] = '';
$server['REQUEST_METHOD'] = strtoupper($method);
@@ -235,6 +239,7 @@ class Request
$options['pathinfo'] = ltrim($info['path'], '/');
$options['method'] = $server['REQUEST_METHOD'];
$options['domain'] = $server['HTTP_HOST'];
$options['content'] = $content;
self::$instance = new self($options);
return self::$instance;
}
@@ -983,7 +988,7 @@ class Request
$value = $default;
break;
}
} else {
} elseif (!empty($filter)) {
// filter函数不存在时, 则使用filter_var进行过滤
// filter为非整形值时, 调用filter_id取得过滤id
$value = filter_var($value, is_int($filter) ? $filter : filter_id($filter));
@@ -1289,14 +1294,14 @@ class Request
}
/**
* 获取当前请求的调度信息
* 设置或者获取当前请求的调度信息
* @access public
* @param array $dispatch 调度信息
* @param array $dispatch 调度信息
* @return array
*/
public function dispatch($dispatch = [])
public function dispatch($dispatch = null)
{
if (!empty($dispatch)) {
if (!is_null($dispatch)) {
$this->dispatch = $dispatch;
}
return $this->dispatch;
@@ -1366,4 +1371,16 @@ class Request
}
}
/**
* 设置或者获取当前请求的content
* @access public
* @return string
*/
public function getContent()
{
if (is_null($this->content)) {
$this->content = file_get_contents('php://input');
}
return $this->content;
}
}

View File

@@ -123,19 +123,26 @@ class Route
}
/**
* 设置和读取路由绑定
* 设置路由绑定
* @access public
* @param string $type 请求类型
* @param mixed $bind 绑定信息
* @param string $type 绑定类型 默认为module
* @return mixed
*/
public static function bind($type, $bind = '')
public static function bind($bind, $type = 'module')
{
if ('' == $bind) {
return isset(self::$bind[$type]) ? self::$bind[$type] : null;
} else {
self::$bind = ['type' => $type, $type => $bind];
}
self::$bind = ['type' => $type, $type => $bind];
}
/**
* 读取路由绑定
* @access public
* @param string $type 绑定类型
* @return mixed
*/
public static function getBind($type)
{
return isset(self::$bind[$type]) ? self::$bind[$type] : null;
}
/**
@@ -210,8 +217,8 @@ class Route
*/
public static function rule($rule, $route = '', $type = '*', $option = [], $pattern = [], $group = '')
{
$group = $group ?: self::$group;
$type = strtoupper($type);
$group = $group ?: self::$group;
$type = strtoupper($type);
if (strpos($type, '|')) {
foreach (explode('|', $type) as $val) {
self::rule($rule, $route, $val, $option, $pattern, $group);
@@ -497,11 +504,12 @@ class Route
* @param string $route 路由地址
* @param string $method 请求类型
* @param array $option 路由参数
* @param string $group 路由分组
* @return void
*/
public static function miss($route, $method = '*', $option = [])
public static function miss($route, $method = '*', $option = [], $group = '')
{
self::rule('__miss__', $route, $method, $option, []);
self::rule('__miss__', $route, $method, $option, [], $group);
}
/**
@@ -522,7 +530,7 @@ class Route
/**
* 检测子域名部署
* @access public
* @param Request $request Request请求对象
* @param Request $request Request请求对象
* @return void
*/
public static function checkDomain($request)
@@ -648,13 +656,13 @@ class Route
// 路由不匹配
} elseif (0 === strpos($rule, '\\')) {
// 路由到类
return self::bindToClass($array[1], substr($rule, 1));
return self::bindToClass($array[1], substr($rule, 1), $depr);
} elseif (0 === strpos($url, '@')) {
// 路由到控制器类
return self::bindToController($array[1], substr($rule, 1));
return self::bindToController($array[1], substr($rule, 1), $depr);
} else {
// 路由到模块/控制器
return self::bindToModule($array[1], $rule);
return self::bindToModule($array[1], $rule, $depr);
}
}
@@ -671,18 +679,13 @@ class Route
self::checkDomain($request);
}
// 检测URL绑定
$return = self::checkUrlBind($url, $rules);
$return = self::checkUrlBind($url, $rules, $depr);
if ($return) {
return $return;
}
// 路由规则检测
if (!empty($rules)) {
if (isset($rules['__miss__'])) {
// 指定未匹配路由的处理
$miss = $rules['__miss__'];
unset($rules['__miss__']);
}
foreach ($rules as $rule => $val) {
$option = isset($val['option']) ? $val['option'] : [];
$pattern = isset($val['pattern']) ? $val['pattern'] : [];
@@ -691,7 +694,11 @@ class Route
if (!self::checkOption($option, $url, $request)) {
continue;
}
if ('__miss__' == $rule) {
// 指定分组MISS路由
$miss = $val['route'];
continue;
}
if (!empty($val['routes'])) {
// 分组路由
if (($pos = strpos($rule, ':')) || ($pos = strpos($rule, '<'))) {
@@ -702,13 +709,12 @@ class Route
if (0 !== strpos($url, $str)) {
continue;
}
$missGroup = false;
// 匹配到路由分组
foreach ($val['routes'] as $key => $route) {
if (is_numeric($key)) {
$key = array_shift($route);
}
$key = $rule . ($key ? '/' . ltrim($key, '/') : '');
// 检查规则路由
if (is_array($route)) {
$option1 = $route[1];
@@ -720,12 +726,27 @@ class Route
$route = $route[0];
$option = array_merge($option, $option1);
}
if ('__miss__' == $key) {
// 指定分组MISS路由
$missGroup = $route;
continue;
}
$key = $rule . ($key ? '/' . ltrim($key, '/') : '');
$result = self::checkRule($key, $route, $url, $pattern, $option);
if (false !== $result) {
$request->route(['rule' => $key, 'route' => $route, 'pattern' => $pattern, 'option' => $option]);
return $result;
}
}
if ($missGroup) {
// 未匹配所有路由的路由规则处理
if ($missGroup instanceof \Closure) {
// 执行闭包
return ['type' => 'function', 'function' => $missGroup, 'params' => []];
} else {
return self::parseRule('', $missGroup, $url, []);
}
}
} else {
if (is_numeric($rule)) {
$rule = array_shift($val);
@@ -742,11 +763,11 @@ class Route
}
if (isset($miss)) {
// 未匹配所有路由的路由规则处理
if ($miss['route'] instanceof \Closure) {
if ($miss instanceof \Closure) {
// 执行闭包
return ['type' => 'function', 'function' => $miss['route'], 'params' => []];
} elseif (self::checkOption($miss['option'], $url, $request)) {
return self::parseRule('', $miss['route'], $url, []);
return ['type' => 'function', 'function' => $miss, 'params' => []];
} else {
return self::parseRule('', $miss, $url, []);
}
}
}
@@ -758,9 +779,10 @@ class Route
* @access private
* @param string $url URL地址
* @param array $rules 路由规则
* @param string $depr URL分隔符
* @return false
*/
private static function checkUrlBind(&$url, &$rules)
private static function checkUrlBind(&$url, &$rules, $depr = '/')
{
if (!empty(self::$bind['type'])) {
// 记录绑定信息
@@ -769,10 +791,10 @@ class Route
switch (self::$bind['type']) {
case 'class':
// 绑定到类
return self::bindToClass($url, self::$bind['class']);
return self::bindToClass($url, self::$bind['class'], $depr);
case 'namespace':
// 绑定到命名空间
return self::bindToNamespace($url, self::$bind['namespace']);
return self::bindToNamespace($url, self::$bind['namespace'], $depr);
case 'module':
// 如果有模块/控制器绑定 针对路由到 模块/控制器 有效
$url = self::$bind['module'] . '/' . $url;
@@ -793,15 +815,17 @@ class Route
* @access public
* @param string $url URL地址
* @param string $class 类名(带命名空间)
* @param string $depr URL分隔符
* @return array
*/
public static function bindToClass($url, $class)
public static function bindToClass($url, $class, $depr = '/')
{
$array = explode('/', $url, 2);
$array = explode($depr, $url, 2);
$action = !empty($array[0]) ? $array[0] : Config::get('default_action');
if (!empty($array[1])) {
self::parseUrlParams($array[1]);
}
return ['type' => 'method', 'method' => [$class, $array[0] ?: Config::get('default_action')], 'params' => []];
return ['type' => 'method', 'method' => [$class, $action], 'params' => []];
}
/**
@@ -809,11 +833,12 @@ class Route
* @access public
* @param string $url URL地址
* @param string $namespace 命名空间
* @param string $depr URL分隔符
* @return array
*/
public static function bindToNamespace($url, $namespace)
public static function bindToNamespace($url, $namespace, $depr = '/')
{
$array = explode('/', $url, 3);
$array = explode($depr, $url, 3);
$class = !empty($array[0]) ? $array[0] : Config::get('default_controller');
$method = !empty($array[1]) ? $array[1] : Config::get('default_action');
if (!empty($array[2])) {
@@ -822,21 +847,43 @@ class Route
return ['type' => 'method', 'method' => [$namespace . '\\' . $class, $method], 'params' => []];
}
/**
* 绑定到应用 直接进行控制器类库访问
* @access public
* @param string $url URL地址
* @param string $depr URL分隔符
* @return array
*/
public static function bindToApp($url, $depr = '/')
{
$array = explode($depr, $url, 4);
$module = !empty($array[0]) ? $array[0] : Config::get('default_module');
$controller = !empty($array[1]) ? $array[1] : Config::get('default_controller');
$method = !empty($array[2]) ? $array[2] : Config::get('default_action');
$layer = Config::get('url_controller_layer');
$class = App::$namespace . '\\' . $module . '\\' . $layer . '\\' . $controller;
if (!empty($array[3])) {
self::parseUrlParams($array[3]);
}
return ['type' => 'method', 'method' => [$class, $method], 'params' => []];
}
/**
* 绑定到控制器类
* @access public
* @param string $url URL地址
* @param string $module 模块名
* @param string $controller 控制器名 (支持带模块名 index/user
* @param string $depr URL分隔符
* @return array
*/
public static function bindToController($url, $controller)
public static function bindToController($url, $controller, $depr = '/')
{
$array = explode('/', $url, 2);
$array = explode($depr, $url, 2);
$action = !empty($array[0]) ? $array[0] : Config::get('default_action');
if (!empty($array[1])) {
self::parseUrlParams($array[1]);
}
return ['type' => 'method', 'method' => [$controller, $action], 'params' => []];
return ['type' => 'controller', 'controller' => $controller . '/' . $action, 'params' => []];
}
/**
@@ -844,11 +891,12 @@ class Route
* @access public
* @param string $url URL地址
* @param string $class 控制器类名(带命名空间)
* @param string $depr URL分隔符
* @return array
*/
public static function bindToModule($url, $controller)
public static function bindToModule($url, $controller, $depr = '/')
{
$array = explode('/', $url, 2);
$array = explode($depr, $url, 2);
$action = !empty($array[0]) ? $array[0] : Config::get('default_action');
if (!empty($array[1])) {
self::parseUrlParams($array[1]);
@@ -883,8 +931,8 @@ class Route
* 检测路由规则
* @access private
* @param string $rule 路由规则
* @param string $url URL地址
* @param string $route 路由地址
* @param string $url URL地址
* @param array $pattern 变量规则
* @param array $option 路由参数
* @return array|false
@@ -910,7 +958,7 @@ class Route
if ($len1 >= $len2 || strpos($rule, '[')) {
if ('$' == substr($rule, -1, 1)) {
// 完整匹配
if (!$merge && $len1 != $len2 && false === strpos($rule, '[')) {
if (!$merge && $len1 != $len2 && (false === strpos($rule, '[') || $len1 > $len2 || $len1 < $len2 - substr_count($rule, '['))) {
return false;
} else {
$rule = substr($rule, 0, -1);
@@ -924,12 +972,12 @@ class Route
if ($option['after_behavior'] instanceof \Closure) {
$result = call_user_func_array($option['after_behavior'], [$route]);
} else {
foreach((array)$option['after_behavior'] as $behavior){
foreach ((array) $option['after_behavior'] as $behavior) {
$result = Hook::exec($behavior, '', $route);
if (!is_null($result)) {
break;
}
}
}
}
// 路由规则重定向
if ($result instanceof Response) {
@@ -954,10 +1002,9 @@ class Route
* @param string $url URL地址
* @param string $depr URL分隔符
* @param bool $autoSearch 是否自动深度搜索控制器
* @param integer $paramType URL参数解析方式 0 名称解析 1 顺序解析
* @return array
*/
public static function parseUrl($url, $depr = '/', $autoSearch = false, $paramType = 0)
public static function parseUrl($url, $depr = '/', $autoSearch = false)
{
if (isset(self::$bind['module'])) {
// 如果有模块/控制器绑定
@@ -968,24 +1015,46 @@ class Route
$url = str_replace($depr, '/', $url);
}
$result = self::parseRoute($url, $autoSearch, true, $paramType);
if (!empty($result['var'])) {
$_GET = array_merge($result['var'], $_GET);
list($path, $var) = self::parseUrlPath($url);
$route = [null, null, null];
if (isset($path)) {
// 解析模块
$module = Config::get('app_multi_module') ? array_shift($path) : null;
if ($autoSearch) {
// 自动搜索控制器
$dir = APP_PATH . ($module ? $module . DS : '') . 'controller';
$suffix = App::$suffix || Config::get('controller_suffix') ? ucfirst(Config::get('url_controller_layer')) : '';
$item = [];
foreach ($path as $val) {
$item[] = array_shift($path);
if (is_file($dir . DS . $val . $suffix . EXT)) {
break;
} else {
$dir .= DS . $val;
}
}
$controller = implode('.', $item);
} else {
// 解析控制器
$controller = !empty($path) ? array_shift($path) : null;
}
// 解析操作
$action = !empty($path) ? array_shift($path) : null;
// 解析额外参数
self::parseUrlParams(empty($path) ? '' : implode('/', $path));
// 封装路由
$route = [$module, $controller, $action];
}
return ['type' => 'module', 'module' => $result['route']];
return ['type' => 'module', 'module' => $route];
}
/**
* 解析规范的路由地址 地址格式 [模块/控制器/操作?]参数1=值1&参数2=值2...
* 解析URL的pathinfo参数和变量
* @access private
* @param string $url URL地址
* @param bool $autoSearch 是否自动深度搜索控制器
* @param bool $reverse 是否反转解析URL
* @param integer $paramType URL参数解析方式 0 名称解析 1 顺序解析
* @return array
*/
private static function parseRoute($url, $autoSearch = false, $reverse = false, $paramType = 0)
private static function parseUrlPath($url)
{
$url = trim($url, '/');
$var = [];
@@ -1003,58 +1072,7 @@ class Route
} else {
$path = [$url];
}
$route = [null, null, null];
if (isset($path)) {
if ($reverse) {
// 解析模块
$module = Config::get('app_multi_module') ? array_shift($path) : null;
if ($autoSearch) {
// 自动搜索控制器
$dir = APP_PATH . ($module ? $module . DS : '') . 'controller';
$suffix = App::$suffix || Config::get('controller_suffix') ? ucfirst(Config::get('url_controller_layer')) : '';
$item = [];
foreach ($path as $val) {
$item[] = array_shift($path);
if (is_file($dir . DS . $val . $suffix . EXT)) {
break;
} else {
$dir .= DS . $val;
}
}
$controller = implode('.', $item);
} else {
// 解析控制器
$controller = !empty($path) ? array_shift($path) : null;
}
// 解析操作
$action = !empty($path) ? array_shift($path) : null;
// 解析额外参数
if (!empty($path)) {
if ($paramType) {
$var += $path;
} else {
preg_replace_callback('/([^\/]+)\/([^\/]+)/', function ($match) use (&$var) {
$var[strtolower($match[1])] = strip_tags($match[2]);
}, implode('/', $path));
}
}
} else {
$action = array_pop($path);
$controller = !empty($path) ? array_pop($path) : null;
$module = Config::get('app_multi_module') && !empty($path) ? array_pop($path) : null;
$method = Request::instance()->method();
// REST 操作方法支持
if ('[rest]' == $action) {
$action = $method;
} elseif (Config::get('use_action_prefix') && !empty(self::$methodPrefix[$method])) {
// 操作方法前缀支持
$action = 0 !== strpos($action, self::$methodPrefix[$method]) ? self::$methodPrefix[$method] . $action : $action;
}
}
// 封装路由
$route = [$module, $controller, $action];
}
return ['route' => $route, 'var' => $var];
return [$path, $var];
}
/**
@@ -1166,14 +1184,22 @@ class Route
// 路由到控制器
$result = ['type' => 'controller', 'controller' => substr($url, 1), 'params' => $matches];
} else {
// 解析路由地址
$result = self::parseRoute($url);
$var = array_merge($matches, $result['var']);
// 解析剩余的URL参数
self::parseUrlParams(implode('/', $paths), $var);
// 路由到模块/控制器/操作
$result = ['type' => 'module', 'module' => $result['route'], 'convert' => false];
list($path, $var) = self::parseUrlPath($url);
$action = array_pop($path);
$controller = !empty($path) ? array_pop($path) : null;
$module = Config::get('app_multi_module') && !empty($path) ? array_pop($path) : null;
$method = Request::instance()->method();
if (Config::get('use_action_prefix') && !empty(self::$methodPrefix[$method])) {
// 操作方法前缀支持
$action = 0 !== strpos($action, self::$methodPrefix[$method]) ? self::$methodPrefix[$method] . $action : $action;
}
$_GET = array_merge($_GET, $var);
// 路由到模块/控制器/操作
$result = ['type' => 'module', 'module' => [$module, $controller, $action], 'convert' => false];
}
// 解析额外参数
self::parseUrlParams(empty($paths) ? '' : implode('/', $paths), $matches);
return $result;
}
@@ -1191,11 +1217,10 @@ class Route
$var += explode('/', $url);
} else {
preg_replace_callback('/(\w+)\/([^\/]+)/', function ($match) use (&$var) {
$var[strtolower($match[1])] = strip_tags($match[2]);
$var[$match[1]] = strip_tags($match[2]);
}, $url);
}
}
// 设置当前请求的参数
Request::instance()->param(array_merge($var, $_GET));
}

View File

@@ -672,7 +672,7 @@ class Template
*/
public function parseTagLib($tagLib, &$content, $hide = false)
{
if (strpos($tagLib, '\\')) {
if (false !== strpos($tagLib, '\\')) {
// 支持指定标签库的命名空间
$className = $tagLib;
$tagLib = substr($tagLib, strrpos($tagLib, '\\') + 1);

View File

@@ -78,9 +78,9 @@ class Url
}
// 检测URL绑定
$type = Route::bind('type');
$type = Route::getBind('type');
if ($type) {
$bind = Route::bind($type);
$bind = Route::getBind($type);
if (0 === strpos($url, $bind)) {
$url = substr($url, strlen($bind) + 1);
}
@@ -153,9 +153,10 @@ class Url
protected static function parseDomain(&$url, $domain)
{
if ($domain) {
$request = Request::instance();
if (true === $domain) {
// 自动判断域名
$domain = $_SERVER['HTTP_HOST'];
$domain = $request->host();
if (Config::get('url_domain_deploy')) {
// 根域名
$urlDomainRoot = Config::get('url_domain_root');
@@ -184,9 +185,9 @@ class Url
}
}
} else {
$domain .= strpos($domain, '.') ? '' : strstr($_SERVER['HTTP_HOST'], '.');
$domain .= strpos($domain, '.') ? '' : strstr($request->host(), '.');
}
$domain = (self::isSsl() ? 'https://' : 'http://') . $domain;
$domain = ($request->isSsl() ? 'https://' : 'http://') . $domain;
} else {
$domain = '';
}
@@ -217,20 +218,6 @@ class Url
return (empty($suffix) || 0 === strpos($suffix, '.')) ? $suffix : '.' . $suffix;
}
/**
* 判断是否SSL协议
* @return boolean
*/
public static function isSsl()
{
if (isset($_SERVER['HTTPS']) && ('1' == $_SERVER['HTTPS'] || 'on' == strtolower($_SERVER['HTTPS']))) {
return true;
} elseif (isset($_SERVER['SERVER_PORT']) && ('443' == $_SERVER['SERVER_PORT'])) {
return true;
}
return false;
}
// 匹配路由地址
public static function getRouteUrl($alias, &$vars = [])
{
@@ -253,11 +240,13 @@ class Url
}
}
$match = true;
} elseif (empty($pattern) && array_intersect_assoc($param, $array) == $param) {
$match = true;
}
if (empty($pattern) && empty($param)) {
// 没有任何变量
return $url;
} elseif ($match && (empty($param) || array_intersect_assoc($param, $array) == $param)) {
if (!empty($param) && array_intersect_assoc($param, $array) != $param) {
$match = false;
}
if ($match) {
// 存在变量定义
$vars = array_diff_key($array, $param);
return $url;

View File

@@ -16,11 +16,11 @@ use PDOStatement;
use think\App;
use think\Collection;
use think\Db;
use think\db\exception\BindParamException;
use think\db\Query;
use think\Debug;
use think\Exception;
use think\exception\PDOException;
use think\db\exception\BindParamException;
use think\Log;
abstract class Connection
@@ -102,7 +102,7 @@ abstract class Connection
// PDO连接参数
protected $params = [
PDO::ATTR_CASE => PDO::CASE_LOWER,
PDO::ATTR_CASE => PDO::CASE_NATURAL,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
PDO::ATTR_STRINGIFY_FETCHES => false,
@@ -188,7 +188,7 @@ abstract class Connection
* @param array $info 字段信息
* @return array
*/
protected function fieldCase($info)
public function fieldCase($info)
{
// 字段大小写转换
switch ($this->attrCase) {
@@ -330,7 +330,7 @@ abstract class Connection
}
// 根据参数绑定组装最终的SQL语句
$this->queryStr = $this->getRealSql($sql, $bind);
//释放前次的查询结果
if (!empty($this->PDOStatement)) {
$this->free();
@@ -474,6 +474,7 @@ abstract class Connection
return $this->PDOStatement;
}
if ($procedure) {
// 存储过程返回结果
return $this->procedure($class);
}
$result = $this->PDOStatement->fetchAll($this->fetchType);
@@ -482,11 +483,10 @@ abstract class Connection
if (!empty($class)) {
// 返回指定数据集对象类
$result = new $class($result);
} elseif ('collection' == $this->resultSetType){
} elseif ('collection' == $this->resultSetType) {
// 返回数据集Collection对象
$result = new Collection($result);
}
return $result;
}
@@ -551,7 +551,7 @@ abstract class Connection
++$this->transTimes;
if ($this->transTimes == 1) {
if (1 == $this->transTimes) {
$this->linkID->beginTransaction();
} elseif ($this->transTimes > 1 && $this->supportSavepoint()) {
$this->linkID->exec(
@@ -570,7 +570,7 @@ abstract class Connection
{
$this->initConnect(true);
if ($this->transTimes == 1) {
if (1 == $this->transTimes) {
$this->linkID->commit();
}
@@ -587,7 +587,7 @@ abstract class Connection
{
$this->initConnect(true);
if ($this->transTimes == 1) {
if (1 == $this->transTimes) {
$this->linkID->rollBack();
} elseif ($this->transTimes > 1 && $this->supportSavepoint()) {
$this->linkID->exec(
@@ -647,9 +647,9 @@ abstract class Connection
}
// 提交事务
$this->commit();
} catch (\PDOException $e) {
} catch (\Exception $e) {
$this->rollback();
return false;
throw $e;
}
return true;
}

View File

@@ -18,10 +18,10 @@ use think\db\Builder;
*/
class Sqlsrv extends Builder
{
protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%';
protected $selectSql = 'SELECT T1.* FROM (SELECT thinkphp.*, ROW_NUMBER() OVER (%ORDER%) AS ROW_NUMBER FROM (SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%) AS thinkphp) AS T1 %LIMIT%%COMMENT%';
protected $selectInsertSql = 'SELECT %DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%';
protected $updateSql = 'UPDATE %TABLE% SET %SET% %JOIN% %WHERE% %LIMIT% %LOCK%%COMMENT%';
protected $deleteSql = 'DELETE FROM %TABLE% %USING% %JOIN% %WHERE% %LIMIT% %LOCK%%COMMENT%';
protected $updateSql = 'UPDATE %TABLE% SET %SET% %JOIN% %WHERE% %LIMIT% %LOCK%%COMMENT%';
protected $deleteSql = 'DELETE FROM %TABLE% %USING% %JOIN% %WHERE% %LIMIT% %LOCK%%COMMENT%';
/**
* order分析
@@ -79,9 +79,10 @@ class Sqlsrv extends Builder
}
return 'WHERE ' . $limitStr;
}
public function selectInsert($fields, $table, $options)
public function selectInsert($fields, $table, $options)
{
$this->selectSql=$this->selectInsertSql;
$this->selectSql = $this->selectInsertSql;
return parent::selectInsert($fields, $table, $options);
}

View File

@@ -250,7 +250,7 @@ class Merge extends Model
return $result;
} catch (\Exception $e) {
$db->rollback();
return false;
throw $e;
}
}
@@ -283,9 +283,9 @@ class Merge extends Model
$this->trigger('after_delete', $this);
$db->commit();
return $result;
} catch (\PDOException $e) {
} catch (\Exception $e) {
$db->rollback();
return false;
throw $e;
}
}

View File

@@ -16,6 +16,7 @@ use think\Exception;
class Redis extends SessionHandler
{
/** @var \Redis */
protected $handler = null;
protected $config = [
'host' => '127.0.0.1', // redis主机
@@ -35,8 +36,10 @@ class Redis extends SessionHandler
/**
* 打开Session
* @access public
* @param string $savePath
* @param mixed $sessName
* @param string $savePath
* @param mixed $sessName
* @return bool
* @throws Exception
*/
public function open($savePath, $sessName)
{
@@ -72,6 +75,7 @@ class Redis extends SessionHandler
* 读取Session
* @access public
* @param string $sessID
* @return bool|string
*/
public function read($sessID)
{
@@ -83,6 +87,7 @@ class Redis extends SessionHandler
* @access public
* @param string $sessID
* @param String $sessData
* @return bool
*/
public function write($sessID, $sessData)
{
@@ -97,16 +102,18 @@ class Redis extends SessionHandler
* 删除Session
* @access public
* @param string $sessID
* @return bool|void
*/
public function destroy($sessID)
{
return $this->handler->delete($this->config['session_name'] . $sessID) ? true : false;
$this->handler->delete($this->config['session_name'] . $sessID);
}
/**
* Session 垃圾回收
* @access public
* @param string $sessMaxLifeTime
* @return bool
*/
public function gc($sessMaxLifeTime)
{

View File

@@ -87,15 +87,15 @@ class TagLib
public function parseTag(&$content, $lib = '')
{
$tags = [];
$_lib = $lib ? $lib . ':' : '';
$lib = $lib ? strtolower($lib) . ':' : '';
foreach ($this->tags as $name => $val) {
$close = !isset($val['close']) || $val['close'] ? 1 : 0;
$tags[$close][$_lib . $name] = $name;
$close = !isset($val['close']) || $val['close'] ? 1 : 0;
$tags[$close][$lib . $name] = $name;
if (isset($val['alias'])) {
// 别名设置
$array = (array) $val['alias'];
foreach (explode(',', $array[0]) as $v) {
$tags[$close][$_lib . $v] = $name;
$tags[$close][$lib . $v] = $name;
}
}
}
@@ -108,7 +108,7 @@ class TagLib
$right = [];
foreach ($matches as $match) {
if ('' == $match[1][0]) {
$name = $match[2][0];
$name = strtolower($match[2][0]);
// 如果有没闭合的标签头则取出最后一个
if (!empty($right[$name])) {
// $match[0][1]为标签结束符在模板中的位置
@@ -120,7 +120,7 @@ class TagLib
}
} else {
// 标签头压入栈
$right[$match[1][0]][] = $match[0];
$right[strtolower($match[1][0])][] = $match[0];
}
}
unset($right, $matches);
@@ -135,10 +135,10 @@ class TagLib
foreach ($nodes as $pos => $node) {
// 对应的标签名
$name = $tags[1][$node['name']];
$alias = $_lib . $name != $node['name'] ? ($_lib ? strstr($node['name'], $_lib) : $node['name']) : '';
$alias = $lib . $name != $node['name'] ? ($lib ? strstr($node['name'], $lib) : $node['name']) : '';
// 解析标签属性
$attrs = $this->parseAttr($node['begin'][0], $name, $alias);
$method = '_' . $name;
$method = 'tag' . $name;
// 读取标签库中对应的标签内容 replace[0]用来替换标签头replace[1]用来替换标签尾
$replace = explode($break, $this->$method($attrs, $break));
if (count($replace) > 1) {
@@ -170,13 +170,13 @@ class TagLib
// 自闭合标签
if (!empty($tags[0])) {
$regex = $this->getRegex(array_keys($tags[0]), 0);
$content = preg_replace_callback($regex, function ($matches) use (&$tags, &$_lib) {
$content = preg_replace_callback($regex, function ($matches) use (&$tags, &$lib) {
// 对应的标签名
$name = $tags[0][$matches[1]];
$alias = $_lib . $name != $matches[1] ? ($_lib ? strstr($matches[1], $_lib) : $matches[1]) : '';
$name = $tags[0][strtolower($matches[1])];
$alias = $lib . $name != $matches[1] ? ($lib ? strstr($matches[1], $lib) : $matches[1]) : '';
// 解析标签属性
$attrs = $this->parseAttr($matches[0], $name, $alias);
$method = '_' . $name;
$method = 'tag' . $name;
return $this->$method($attrs, '');
}, $content);
}
@@ -286,6 +286,9 @@ class TagLib
*/
public function parseCondition($condition)
{
if (strpos($condition, ':')) {
$condition = ' ' . substr(strstr($condition, ':'), 1);
}
$condition = str_ireplace(array_keys($this->comparison), array_values($this->comparison), $condition);
$this->tpl->parseVar($condition);
// $this->tpl->parseVarFunction($condition); // XXX: 此句能解析表达式中用|分隔的函数,但表达式中如果有|、||这样的逻辑运算就产生了歧异

View File

@@ -43,8 +43,7 @@ class Cx extends Taglib
'notpresent' => ['attr' => 'name'],
'defined' => ['attr' => 'name'],
'notdefined' => ['attr' => 'name'],
'import' => ['attr' => 'file,href,type,value,basepath', 'close' => 0],
'load' => ['attr' => 'file,href,type,value,basepath', 'close' => 0, 'alias' => ['css,js', 'type']],
'load' => ['attr' => 'file,href,type,value,basepath', 'close' => 0, 'alias' => ['import,css,js', 'type']],
'assign' => ['attr' => 'name,value', 'close' => 0],
'define' => ['attr' => 'name,value', 'close' => 0],
'for' => ['attr' => 'start,end,name,comparison,step'],
@@ -61,7 +60,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _php($tag, $content)
public function tagPhp($tag, $content)
{
$parseStr = '<?php ' . $content . ' ?>';
return $parseStr;
@@ -79,7 +78,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string|void
*/
public function _volist($tag, $content)
public function tagVolist($tag, $content)
{
$name = $tag['name'];
$id = $tag['id'];
@@ -131,7 +130,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string|void
*/
public function _foreach($tag, $content)
public function tagForeach($tag, $content)
{
// 直接使用表达式
if (!empty($tag['expression'])) {
@@ -212,7 +211,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _if($tag, $content)
public function tagIf($tag, $content)
{
$condition = !empty($tag['expression']) ? $tag['expression'] : $tag['condition'];
$condition = $this->parseCondition($condition);
@@ -228,7 +227,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _elseif($tag, $content)
public function tagElseif($tag, $content)
{
$condition = !empty($tag['expression']) ? $tag['expression'] : $tag['condition'];
$condition = $this->parseCondition($condition);
@@ -243,7 +242,7 @@ class Cx extends Taglib
* @param array $tag 标签属性
* @return string
*/
public function _else($tag)
public function tagElse($tag)
{
$parseStr = '<?php else: ?>';
return $parseStr;
@@ -262,7 +261,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _switch($tag, $content)
public function tagSwitch($tag, $content)
{
$name = !empty($tag['expression']) ? $tag['expression'] : $tag['name'];
$name = $this->autoBuildVar($name);
@@ -277,7 +276,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _case($tag, $content)
public function tagCase($tag, $content)
{
$value = !empty($tag['expression']) ? $tag['expression'] : $tag['value'];
$flag = substr($value, 0, 1);
@@ -309,7 +308,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _default($tag)
public function tagDefault($tag)
{
$parseStr = '<?php default: ?>';
return $parseStr;
@@ -324,7 +323,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _compare($tag, $content)
public function tagCompare($tag, $content)
{
$name = $tag['name'];
$value = $tag['value'];
@@ -359,7 +358,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _range($tag, $content)
public function tagRange($tag, $content)
{
$name = $tag['name'];
$value = $tag['value'];
@@ -394,7 +393,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _present($tag, $content)
public function tagPresent($tag, $content)
{
$name = $tag['name'];
$name = $this->autoBuildVar($name);
@@ -411,7 +410,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _notpresent($tag, $content)
public function tagNotpresent($tag, $content)
{
$name = $tag['name'];
$name = $this->autoBuildVar($name);
@@ -428,7 +427,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _empty($tag, $content)
public function tagEmpty($tag, $content)
{
$name = $tag['name'];
$name = $this->autoBuildVar($name);
@@ -445,7 +444,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _notempty($tag, $content)
public function tagNotempty($tag, $content)
{
$name = $tag['name'];
$name = $this->autoBuildVar($name);
@@ -460,7 +459,7 @@ class Cx extends Taglib
* @param string $content
* @return string
*/
public function _defined($tag, $content)
public function tagDefined($tag, $content)
{
$name = $tag['name'];
$parseStr = '<?php if(defined("' . $name . '")): ?>' . $content . '<?php endif; ?>';
@@ -474,7 +473,7 @@ class Cx extends Taglib
* @param string $content
* @return string
*/
public function _notdefined($tag, $content)
public function tagNotdefined($tag, $content)
{
$name = $tag['name'];
$parseStr = '<?php if(!defined("' . $name . '")): ?>' . $content . '<?php endif; ?>';
@@ -482,19 +481,17 @@ class Cx extends Taglib
}
/**
* import 标签解析 {import file="Js.Base" /}
* 格式:{import file="Css.Base" type="css" /}
* load 标签解析 {load file="/static/js/base.js" /}
* 格式:{load file="/static/css/base.css" /}
* @access public
* @param array $tag 标签属性
* @param string $content 标签内容
* @param boolean $isFile 是否文件方式
* @param string $type 类型
* @return string
*/
public function _import($tag, $content, $isFile = false)
public function tagLoad($tag, $content)
{
$file = isset($tag['file']) ? $tag['file'] : $tag['href'];
$type = isset($tag['type']) ? strtolower($tag['type']) : ($isFile ? null : 'js');
$type = isset($tag['type']) ? strtolower($tag['type']) : '';
$parseStr = '';
$endStr = '';
// 判断是否存在加载条件 允许使用函数判断(默认为isset)
@@ -505,58 +502,26 @@ class Cx extends Taglib
$parseStr .= '<?php if(' . $name . '): ?>';
$endStr = '<?php endif; ?>';
}
if ($isFile) {
// 文件方式导入
$array = explode(',', $file);
foreach ($array as $val) {
if (!$type || isset($reset)) {
$type = $reset = strtolower(substr(strrchr($val, '.'), 1));
}
switch ($type) {
case 'js':
$parseStr .= '<script type="text/javascript" src="' . $val . '"></script>';
break;
case 'css':
$parseStr .= '<link rel="stylesheet" type="text/css" href="' . $val . '" />';
break;
case 'php':
$parseStr .= '<?php include "' . $val . '"; ?>';
break;
}
}
} else {
// 命名空间导入模式
$basepath = !empty($tag['basepath']) ? $tag['basepath'] : '/public';
// 命名空间方式导入外部文件
$array = explode(',', $file);
foreach ($array as $val) {
if (strpos($val, '?')) {
list($val, $version) = explode('?', $val);
} else {
$version = '';
}
switch ($type) {
case 'js':
$parseStr .= '<script type="text/javascript" src="' . $basepath . '/' . str_replace(['.', '#'], ['/', '.'], $val) . '.js' . ($version ? '?' . $version : '') . '"></script>';
break;
case 'css':
$parseStr .= '<link rel="stylesheet" type="text/css" href="' . $basepath . '/' . str_replace(['.', '#'], ['/', '.'], $val) . '.css' . ($version ? '?' . $version : '') . '" />';
break;
case 'php':
$parseStr .= '<?php \think\Loader::import("' . $val . '"); ?>';
break;
}
// 文件方式导入
$array = explode(',', $file);
foreach ($array as $val) {
$type = strtolower(substr(strrchr($val, '.'), 1));
switch ($type) {
case 'js':
$parseStr .= '<script type="text/javascript" src="' . $val . '"></script>';
break;
case 'css':
$parseStr .= '<link rel="stylesheet" type="text/css" href="' . $val . '" />';
break;
case 'php':
$parseStr .= '<?php include "' . $val . '"; ?>';
break;
}
}
return $parseStr . $endStr;
}
// import别名 采用文件方式加载(要使用命名空间必须用import) 例如 <load file="__PUBLIC__/Js/Base.js" />
public function _load($tag, $content)
{
return $this->_import($tag, $content, true);
}
/**
* assign标签解析
* 在模板中给某个变量赋值 支持变量赋值
@@ -566,7 +531,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _assign($tag, $content)
public function tagAssign($tag, $content)
{
$name = $this->autoBuildVar($tag['name']);
$flag = substr($tag['value'], 0, 1);
@@ -588,7 +553,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _define($tag, $content)
public function tagDefine($tag, $content)
{
$name = '\'' . $tag['name'] . '\'';
$flag = substr($tag['value'], 0, 1);
@@ -612,7 +577,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _for($tag, $content)
public function tagFor($tag, $content)
{
//设置默认值
$start = 0;
@@ -663,7 +628,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _url($tag, $content)
public function tagUrl($tag, $content)
{
$url = isset($tag['link']) ? $tag['link'] : '';
$vars = isset($tag['vars']) ? $tag['vars'] : '';
@@ -689,7 +654,7 @@ class Cx extends Taglib
* @param string $content 标签内容
* @return string
*/
public function _function($tag, $content)
public function tagFunction($tag, $content)
{
$name = !empty($tag['name']) ? $tag['name'] : 'func';
$vars = !empty($tag['vars']) ? $tag['vars'] : '';

View File

@@ -11,43 +11,8 @@
namespace think;
// ThinkPHP 实际引导文件
// ThinkPHP 引导文件
// 加载基础文件
require __DIR__ . '/base.php';
require CORE_PATH . 'Loader.php';
// 加载环境变量配置文件
if (is_file(ROOT_PATH . 'env' . EXT)) {
$env = include ROOT_PATH . 'env' . EXT;
foreach ($env as $key => $val) {
$name = ENV_PREFIX . $key;
if (is_bool($val)) {
$val = $val ? 1 : 0;
}
putenv("$name=$val");
}
}
// 注册命名空间定义
Loader::addNamespace([
'think' => LIB_PATH . 'think' . DS,
'behavior' => LIB_PATH . 'behavior' . DS,
'traits' => LIB_PATH . 'traits' . DS,
]);
// 注册自动加载
Loader::register();
// 加载别名定义
Loader::addMap(include THINK_PATH . 'alias' . EXT);
// 注册错误和异常处理机制
Error::register();
// 加载模式配置文件
Config::set(include THINK_PATH . 'convention' . EXT);
// 是否自动运行
if (APP_AUTO_RUN) {
App::run()->send();
}
// 执行应用
App::run()->send();

View File

@@ -1,3 +1,80 @@
<?php
if(!function_exists('parse_padding')){
function parse_padding($source)
{
$length = strlen(strval(count($source['source']) + $source['first']));
return 40 + ($length - 1) * 8;
}
}
if(!function_exists('parse_class')){
function parse_class($name)
{
$names = explode('\\', $name);
return '<abbr title="'.$name.'">'.end($names).'</abbr>';
}
}
if(!function_exists('parse_file')){
function parse_file($file, $line)
{
return '<a class="toggle" title="'."{$file} line {$line}".'">'.basename($file)." line {$line}".'</a>';
}
}
if(!function_exists('parse_args')){
function parse_args($args)
{
$result = [];
foreach ($args as $key => $item) {
switch (true) {
case is_object($item):
$value = sprintf('<em>object</em>(%s)', parse_class(get_class($item)));
break;
case is_array($item):
if(count($item) > 3){
$value = sprintf('[%s, ...]', parse_args(array_slice($item, 0, 3)));
} else {
$value = sprintf('[%s]', parse_args($item));
}
break;
case is_string($item):
if(strlen($item) > 20){
$value = sprintf(
'\'<a class="toggle" title="%s">%s...</a>\'',
htmlentities($item),
htmlentities(substr($item, 0, 20))
);
} else {
$value = sprintf("'%s'", htmlentities($item));
}
break;
case is_int($item):
case is_float($item):
$value = $item;
break;
case is_null($item):
$value = '<em>null</em>';
break;
case is_bool($item):
$value = '<em>' . ($item ? 'true' : 'false') . '</em>';
break;
case is_resource($item):
$value = '<em>resource</em>';
break;
default:
$value = htmlentities(str_replace("\n", '', var_export(strval($item), true)));
break;
}
$result[] = is_int($key) ? $value : "'{$key}' => {$value}";
}
return implode(', ', $result);
}
}
?>
<!DOCTYPE html>
<html>
<head>
@@ -399,72 +476,4 @@
</script>
<?php } ?>
</body>
</html>
<?php
function parse_padding($source)
{
$length = strlen(strval(count($source['source']) + $source['first']));
return 40 + ($length - 1) * 8;
}
function parse_class($name)
{
$names = explode('\\', $name);
return '<abbr title="'.$name.'">'.end($names).'</abbr>';
}
function parse_file($file, $line)
{
return '<a class="toggle" title="'."{$file} line {$line}".'">'.basename($file)." line {$line}".'</a>';
}
function parse_args($args)
{
$result = [];
foreach ($args as $key => $item) {
switch (true) {
case is_object($item):
$value = sprintf('<em>object</em>(%s)', parse_class(get_class($item)));
break;
case is_array($item):
if(count($item) > 3){
$value = sprintf('[%s, ...]', parse_args(array_slice($item, 0, 3)));
} else {
$value = sprintf('[%s]', parse_args($item));
}
break;
case is_string($item):
if(strlen($item) > 20){
$value = sprintf(
'\'<a class="toggle" title="%s">%s...</a>\'',
htmlentities($item),
htmlentities(substr($item, 0, 20))
);
} else {
$value = sprintf("'%s'", htmlentities($item));
}
break;
case is_int($item):
case is_float($item):
$value = $item;
break;
case is_null($item):
$value = '<em>null</em>';
break;
case is_bool($item):
$value = '<em>' . ($item ? 'true' : 'false') . '</em>';
break;
case is_resource($item):
$value = '<em>resource</em>';
break;
default:
$value = htmlentities(str_replace("\n", '', var_export(strval($item), true)));
break;
}
$result[] = is_int($key) ? $value : "'{$key}' => {$value}";
}
return implode(', ', $result);
}
</html>