内核更新

This commit is contained in:
2017-03-16 12:03:34 +08:00
parent b355535009
commit a4d58f9f09
28 changed files with 438 additions and 217 deletions

View File

@@ -29,5 +29,5 @@ return array(
'prefix' => 'admin', 'prefix' => 'admin',
'type' => '', 'type' => '',
'auto_start' => true, 'auto_start' => true,
), )
); );

View File

@@ -9,7 +9,7 @@
// | Author: liu21st <liu21st@gmail.com> // | Author: liu21st <liu21st@gmail.com>
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
define('THINK_VERSION', '5.0.6'); define('THINK_VERSION', '5.0.7');
define('THINK_START_TIME', microtime(true)); define('THINK_START_TIME', microtime(true));
define('THINK_START_MEM', memory_get_usage()); define('THINK_START_MEM', memory_get_usage());
define('EXT', '.php'); define('EXT', '.php');

View File

@@ -85,14 +85,14 @@ class App
$request->filter($config['default_filter']); $request->filter($config['default_filter']);
// 默认语言
Lang::range($config['default_lang']);
if ($config['lang_switch_on']) { if ($config['lang_switch_on']) {
// 开启多语言机制 检测当前语言 // 开启多语言机制 检测当前语言
Lang::detect(); Lang::detect();
} else {
// 读取默认语言
Lang::range($config['default_lang']);
} }
$request->langset(Lang::range()); $request->langset(Lang::range());
// 加载系统语言包 // 加载系统语言包
Lang::load([ Lang::load([
THINK_PATH . 'lang' . DS . $request->langset() . EXT, THINK_PATH . 'lang' . DS . $request->langset() . EXT,
@@ -120,35 +120,7 @@ class App
// 请求缓存检查 // 请求缓存检查
$request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']); $request->cache($config['request_cache'], $config['request_cache_expire'], $config['request_cache_except']);
switch ($dispatch['type']) { $data = self::exec($dispatch, $config);
case 'redirect':
// 执行重定向跳转
$data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']);
break;
case 'module':
// 模块/控制器/操作
$data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null);
break;
case 'controller':
// 执行控制器操作
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = Loader::action($dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix']);
break;
case 'method':
// 执行回调方法
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = self::invokeMethod($dispatch['method'], $vars);
break;
case 'function':
// 执行闭包
$data = self::invokeFunction($dispatch['function']);
break;
case 'response':
$data = $dispatch['response'];
break;
default:
throw new \InvalidArgumentException('dispatch type not support');
}
} catch (HttpResponseException $exception) { } catch (HttpResponseException $exception) {
$data = $exception->getResponse(); $data = $exception->getResponse();
} }
@@ -245,7 +217,7 @@ class App
/** /**
* 绑定参数 * 绑定参数
* @access public * @access private
* @param \ReflectionMethod|\ReflectionFunction $reflect 反射类 * @param \ReflectionMethod|\ReflectionFunction $reflect 反射类
* @param array $vars 变量 * @param array $vars 变量
* @return array * @return array
@@ -261,43 +233,90 @@ class App
} }
} }
$args = []; $args = [];
// 判断数组类型 数字数组时按顺序绑定参数
reset($vars);
$type = key($vars) === 0 ? 1 : 0;
if ($reflect->getNumberOfParameters() > 0) { if ($reflect->getNumberOfParameters() > 0) {
// 判断数组类型 数字数组时按顺序绑定参数
reset($vars);
$type = key($vars) === 0 ? 1 : 0;
$params = $reflect->getParameters(); $params = $reflect->getParameters();
foreach ($params as $param) { foreach ($params as $param) {
$name = $param->getName(); $args[] = self::getParamValue($param, $vars, $type);
$class = $param->getClass();
if ($class) {
$className = $class->getName();
$bind = Request::instance()->$name;
if ($bind instanceof $className) {
$args[] = $bind;
} else {
if (method_exists($className, 'invoke')) {
$method = new \ReflectionMethod($className, 'invoke');
if ($method->isPublic() && $method->isStatic()) {
$args[] = $className::invoke(Request::instance());
continue;
}
}
$args[] = method_exists($className, 'instance') ? $className::instance() : new $className;
}
} elseif (1 == $type && !empty($vars)) {
$args[] = array_shift($vars);
} elseif (0 == $type && isset($vars[$name])) {
$args[] = $vars[$name];
} elseif ($param->isDefaultValueAvailable()) {
$args[] = $param->getDefaultValue();
} else {
throw new \InvalidArgumentException('method param miss:' . $name);
}
} }
} }
return $args; return $args;
} }
/**
* 获取参数值
* @access private
* @param \ReflectionParameter $param
* @param array $vars 变量
* @param string $type
* @return array
*/
private static function getParamValue($param, &$vars, $type)
{
$name = $param->getName();
$class = $param->getClass();
if ($class) {
$className = $class->getName();
$bind = Request::instance()->$name;
if ($bind instanceof $className) {
$result = $bind;
} else {
if (method_exists($className, 'invoke')) {
$method = new \ReflectionMethod($className, 'invoke');
if ($method->isPublic() && $method->isStatic()) {
return $className::invoke(Request::instance());
}
}
$result = method_exists($className, 'instance') ? $className::instance() : new $className;
}
} elseif (1 == $type && !empty($vars)) {
$result = array_shift($vars);
} elseif (0 == $type && isset($vars[$name])) {
$result = $vars[$name];
} elseif ($param->isDefaultValueAvailable()) {
$result = $param->getDefaultValue();
} else {
throw new \InvalidArgumentException('method param miss:' . $name);
}
return $result;
}
protected static function exec($dispatch, $config)
{
switch ($dispatch['type']) {
case 'redirect':
// 执行重定向跳转
$data = Response::create($dispatch['url'], 'redirect')->code($dispatch['status']);
break;
case 'module':
// 模块/控制器/操作
$data = self::module($dispatch['module'], $config, isset($dispatch['convert']) ? $dispatch['convert'] : null);
break;
case 'controller':
// 执行控制器操作
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = Loader::action($dispatch['controller'], $vars, $config['url_controller_layer'], $config['controller_suffix']);
break;
case 'method':
// 执行回调方法
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = self::invokeMethod($dispatch['method'], $vars);
break;
case 'function':
// 执行闭包
$data = self::invokeFunction($dispatch['function']);
break;
case 'response':
$data = $dispatch['response'];
break;
default:
throw new \InvalidArgumentException('dispatch type not support');
}
return $data;
}
/** /**
* 执行模块 * 执行模块
* @access public * @access public

View File

@@ -11,7 +11,6 @@
namespace think; namespace think;
use SplFileInfo;
use SplFileObject; use SplFileObject;
class File extends SplFileObject class File extends SplFileObject
@@ -281,7 +280,7 @@ class File extends SplFileObject
* @param string $path 保存路径 * @param string $path 保存路径
* @param string|bool $savename 保存的文件名 默认自动生成 * @param string|bool $savename 保存的文件名 默认自动生成
* @param boolean $replace 同名文件是否覆盖 * @param boolean $replace 同名文件是否覆盖
* @return false|SplFileInfo false-失败 否则返回SplFileInfo实例 * @return false|File false-失败 否则返回File实例
*/ */
public function move($path, $savename = true, $replace = true) public function move($path, $savename = true, $replace = true)
{ {

View File

@@ -369,8 +369,9 @@ class Loader
if (isset(self::$instance[$guid])) { if (isset(self::$instance[$guid])) {
return self::$instance[$guid]; return self::$instance[$guid];
} }
if (strpos($name, '\\')) { if (false !== strpos($name, '\\')) {
$class = $name; $class = $name;
$module = Request::instance()->module();
} else { } else {
if (strpos($name, '/')) { if (strpos($name, '/')) {
list($module, $name) = explode('/', $name, 2); list($module, $name) = explode('/', $name, 2);
@@ -404,8 +405,9 @@ class Loader
*/ */
public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '') public static function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
{ {
if (strpos($name, '\\')) { if (false !== strpos($name, '\\')) {
$class = $name; $class = $name;
$module = Request::instance()->module();
} else { } else {
if (strpos($name, '/')) { if (strpos($name, '/')) {
list($module, $name) = explode('/', $name); list($module, $name) = explode('/', $name);
@@ -440,8 +442,9 @@ class Loader
if (isset(self::$instance[$guid])) { if (isset(self::$instance[$guid])) {
return self::$instance[$guid]; return self::$instance[$guid];
} }
if (strpos($name, '\\')) { if (false !== strpos($name, '\\')) {
$class = $name; $class = $name;
$module = Request::instance()->module();
} else { } else {
if (strpos($name, '/')) { if (strpos($name, '/')) {
list($module, $name) = explode('/', $name); list($module, $name) = explode('/', $name);

View File

@@ -84,7 +84,7 @@ class Log
public static function record($msg, $type = 'log') public static function record($msg, $type = 'log')
{ {
self::$log[$type][] = $msg; self::$log[$type][] = $msg;
if (IS_CLI && count(self::$log[$type]) > 100) { if (IS_CLI) {
// 命令行下面日志写入改进 // 命令行下面日志写入改进
self::save(); self::save();
} }
@@ -101,7 +101,7 @@ class Log
/** /**
* 当前日志记录的授权key * 当前日志记录的授权key
* @param string $key 授权key * @param string $key 授权key
* @return void * @return void
*/ */
public static function key($key) public static function key($key)
@@ -111,7 +111,7 @@ class Log
/** /**
* 检查日志写入权限 * 检查日志写入权限
* @param array $config 当前日志配置参数 * @param array $config 当前日志配置参数
* @return bool * @return bool
*/ */
public static function check($config) public static function check($config)
@@ -166,13 +166,14 @@ class Log
/** /**
* 实时写入日志信息 并支持行为 * 实时写入日志信息 并支持行为
* @param mixed $msg 调试信息 * @param mixed $msg 调试信息
* @param string $type 信息类型 * @param string $type 信息类型
* @param bool $force 是否强制写入 * @param bool $force 是否强制写入
* @return bool * @return bool
*/ */
public static function write($msg, $type = 'log', $force = false) public static function write($msg, $type = 'log', $force = false)
{ {
$log = self::$log;
// 封装日志信息 // 封装日志信息
if (true === $force || empty(self::$config['level'])) { if (true === $force || empty(self::$config['level'])) {
$log[$type][] = $msg; $log[$type][] = $msg;
@@ -188,7 +189,11 @@ class Log
self::init(Config::get('log')); self::init(Config::get('log'));
} }
// 写入日志 // 写入日志
return self::$driver->save($log, false); $result = self::$driver->save($log);
if ($result) {
self::$log = [];
}
return $result;
} }
/** /**

View File

@@ -290,9 +290,11 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
// 标记字段更改 // 标记字段更改
if (isset($this->data[$name]) && is_scalar($this->data[$name]) && is_scalar($value) && 0 !== strcmp($this->data[$name], $value)) { if (!isset($this->data[$name])) {
$this->change[] = $name; $this->change[] = $name;
} elseif (!isset($this->data[$name]) || $value != $this->data[$name]) { } elseif (is_scalar($value) && is_scalar($this->data[$name]) && 0 !== strcmp($this->data[$name], $value)) {
$this->change[] = $name;
} elseif (!is_object($value) && $value != $this->data[$name]) {
$this->change[] = $name; $this->change[] = $name;
} }
// 设置数据对象属性 // 设置数据对象属性
@@ -378,7 +380,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
if (empty($param)) { if (empty($param)) {
$value = (float) $value; $value = (float) $value;
} else { } else {
$value = (float) number_format($value, $param); $value = (float) number_format($value, $param, '.', '');
} }
break; break;
case 'boolean': case 'boolean':
@@ -486,7 +488,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
if (empty($param)) { if (empty($param)) {
$value = (float) $value; $value = (float) $value;
} else { } else {
$value = (float) number_format($value, $param); $value = (float) number_format($value, $param, '.', '');
} }
break; break;
case 'boolean': case 'boolean':
@@ -508,7 +510,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
$value = json_decode($value, true); $value = json_decode($value, true);
break; break;
case 'array': case 'array':
$value = is_null($value) ? [] : json_decode($value, true); $value = empty($value) ? [] : json_decode($value, true);
break; break;
case 'object': case 'object':
$value = empty($value) ? new \stdClass() : json_decode($value); $value = empty($value) ? new \stdClass() : json_decode($value);
@@ -837,11 +839,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 数据自动完成 // 数据自动完成
$this->autoCompleteData($this->auto); $this->autoCompleteData($this->auto);
// 自动写入更新时间
if ($this->autoWriteTimestamp && $this->updateTime && (empty($this->change) || !in_array($this->updateTime, $this->change))) {
$this->setAttr($this->updateTime, null);
}
// 事件回调 // 事件回调
if (false === $this->trigger('before_write', $this)) { if (false === $this->trigger('before_write', $this)) {
return false; return false;
@@ -873,6 +870,14 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} }
} }
if (empty($data) || (count($data) == 1 && is_string($pk) && isset($data[$pk]))) {
// 没有更新
return 0;
} elseif ($this->autoWriteTimestamp && $this->updateTime && !isset($data[$this->updateTime])) {
// 自动写入更新时间
$data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime);
}
if (empty($where) && !empty($this->updateWhere)) { if (empty($where) && !empty($this->updateWhere)) {
$where = $this->updateWhere; $where = $this->updateWhere;
} }
@@ -919,10 +924,14 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
} else { } else {
// 自动写入 // 自动写入
$this->autoCompleteData($this->insert); $this->autoCompleteData($this->insert);
// 自动写入创建时间和更新时间
// 自动写入创建时间 if ($this->autoWriteTimestamp) {
if ($this->autoWriteTimestamp && $this->createTime && (empty($this->change) || !in_array($this->createTime, $this->change))) { if ($this->createTime && !isset($this->data[$this->createTime])) {
$this->setAttr($this->createTime, null); $this->data[$this->createTime] = $this->autoWriteTimestamp($this->createTime);
}
if ($this->updateTime && !isset($this->data[$this->updateTime])) {
$this->data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime);
}
} }
if (false === $this->trigger('before_insert', $this)) { if (false === $this->trigger('before_insert', $this)) {

View File

@@ -341,7 +341,7 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
{ {
try { try {
$total = $this->total(); $total = $this->total();
} catch (Exception $e) { } catch (\DomainException $e) {
$total = null; $total = null;
} }
@@ -349,7 +349,7 @@ abstract class Paginator implements ArrayAccess, Countable, IteratorAggregate, J
'total' => $total, 'total' => $total,
'per_page' => $this->listRows(), 'per_page' => $this->listRows(),
'current_page' => $this->currentPage(), 'current_page' => $this->currentPage(),
'data' => $this->items->toArray() 'data' => $this->items->toArray(),
]; ];
} }

View File

@@ -633,7 +633,7 @@ class Request
if (true === $name) { if (true === $name) {
// 获取包含文件上传信息的数组 // 获取包含文件上传信息的数组
$file = $this->file(); $file = $this->file();
$data = array_merge($this->param, $file); $data = is_array($file) ? array_merge($this->param, $file) : $this->param;
return $this->input($data, '', $default, $filter); return $this->input($data, '', $default, $filter);
} }
return $this->input($this->param, $name, $default, $filter); return $this->input($this->param, $name, $default, $filter);
@@ -688,7 +688,7 @@ class Request
{ {
if (empty($this->post)) { if (empty($this->post)) {
$content = $this->input; $content = $this->input;
if (empty($_POST) && 'application/json' == $this->contentType()) { if (empty($_POST) && false !== strpos($this->contentType(), 'application/json')) {
$this->post = (array) json_decode($content, true); $this->post = (array) json_decode($content, true);
} else { } else {
$this->post = $_POST; $this->post = $_POST;
@@ -713,7 +713,7 @@ class Request
{ {
if (is_null($this->put)) { if (is_null($this->put)) {
$content = $this->input; $content = $this->input;
if ('application/json' == $this->contentType()) { if (false !== strpos($this->contentType(), 'application/json')) {
$this->put = (array) json_decode($content, true); $this->put = (array) json_decode($content, true);
} else { } else {
parse_str($content, $this->put); parse_str($content, $this->put);
@@ -1357,7 +1357,11 @@ class Request
{ {
$contentType = $this->server('CONTENT_TYPE'); $contentType = $this->server('CONTENT_TYPE');
if ($contentType) { if ($contentType) {
list($type) = explode(';', $contentType); if (strpos($contentType, ';')) {
list($type) = explode(';', $contentType);
} else {
$type = $contentType;
}
return trim($type); return trim($type);
} }
return ''; return '';

View File

@@ -833,7 +833,7 @@ class Route
// 分隔符替换 确保路由定义使用统一的分隔符 // 分隔符替换 确保路由定义使用统一的分隔符
$url = str_replace($depr, '|', $url); $url = str_replace($depr, '|', $url);
if (strpos($url, '|') && isset(self::$rules['alias'][strstr($url, '|', true)])) { if (isset(self::$rules['alias'][$url]) || isset(self::$rules['alias'][strstr($url, '|', true)])) {
// 检测路由别名 // 检测路由别名
$result = self::checkRouteAlias($request, $url, $depr); $result = self::checkRouteAlias($request, $url, $depr);
if (false !== $result) { if (false !== $result) {
@@ -1057,7 +1057,7 @@ class Route
if (!empty($array[1])) { if (!empty($array[1])) {
self::parseUrlParams($array[1]); self::parseUrlParams($array[1]);
} }
return ['type' => 'method', 'method' => [$class, $action]]; return ['type' => 'method', 'method' => [$class, $action], 'var' => []];
} }
/** /**
@@ -1077,7 +1077,7 @@ class Route
if (!empty($array[2])) { if (!empty($array[2])) {
self::parseUrlParams($array[2]); self::parseUrlParams($array[2]);
} }
return ['type' => 'method', 'method' => [$namespace . '\\' . Loader::parseName($class, 1), $method]]; return ['type' => 'method', 'method' => [$namespace . '\\' . Loader::parseName($class, 1), $method], 'var' => []];
} }
/** /**
@@ -1096,7 +1096,7 @@ class Route
if (!empty($array[1])) { if (!empty($array[1])) {
self::parseUrlParams($array[1]); self::parseUrlParams($array[1]);
} }
return ['type' => 'controller', 'controller' => $controller . '/' . $action]; return ['type' => 'controller', 'controller' => $controller . '/' . $action, 'var' => []];
} }
/** /**
@@ -1281,9 +1281,6 @@ class Route
} elseif (strpos($url, '/')) { } elseif (strpos($url, '/')) {
// [模块/控制器/操作] // [模块/控制器/操作]
$path = explode('/', $url); $path = explode('/', $url);
} elseif (false !== strpos($url, '=')) {
// 参数1=值1&参数2=值2...
parse_str($url, $var);
} else { } else {
$path = [$url]; $path = [$url];
} }

View File

@@ -927,7 +927,7 @@ class Template
if (false === strpos($name, '(')) { if (false === strpos($name, '(')) {
$name = '(isset(' . $name . ') && (' . $name . ' !== \'\')?' . $name . ':' . $args[1] . ')'; $name = '(isset(' . $name . ') && (' . $name . ' !== \'\')?' . $name . ':' . $args[1] . ')';
} else { } else {
$name = '(' . $name . ' !== \'\'?' . $name . ':' . $args[1] . ')'; $name = '(' . $name . ' ?: ' . $args[1] . ')';
} }
break; break;
default: // 通用模板函数 default: // 通用模板函数

View File

@@ -268,7 +268,7 @@ class Url
$host = $request->host(); $host = $request->host();
$rootDomain = substr_count($host, '.') > 1 ? substr(strstr($host, '.'), 1) : $host; $rootDomain = substr_count($host, '.') > 1 ? substr(strstr($host, '.'), 1) : $host;
} }
if (!strpos($domain, $rootDomain)) { if (substr_count($domain, '.') < 2 && !strpos($domain, $rootDomain)) {
$domain .= '.' . $rootDomain; $domain .= '.' . $rootDomain;
} }
} }

View File

@@ -98,14 +98,18 @@ abstract class Builder
$result = []; $result = [];
foreach ($data as $key => $val) { foreach ($data as $key => $val) {
$item = $this->parseKey($key, $options); $item = $this->parseKey($key, $options);
if (is_object($val) && method_exists($val, '__toString')) {
// 对象数据写入
$val = $val->__toString();
}
if (false === strpos($key, '.') && !in_array($key, $fields, true)) { if (false === strpos($key, '.') && !in_array($key, $fields, true)) {
if ($options['strict']) { if ($options['strict']) {
throw new Exception('fields not exists:[' . $key . ']'); throw new Exception('fields not exists:[' . $key . ']');
} }
} elseif (isset($val[0]) && 'exp' == $val[0]) {
$result[$item] = $val[1];
} elseif (is_null($val)) { } elseif (is_null($val)) {
$result[$item] = 'NULL'; $result[$item] = 'NULL';
} elseif (isset($val[0]) && 'exp' == $val[0]) {
$result[$item] = $val[1];
} elseif (is_scalar($val)) { } elseif (is_scalar($val)) {
// 过滤非标量数据 // 过滤非标量数据
if (0 === strpos($val, ':') && $this->query->isBind(substr($val, 1))) { if (0 === strpos($val, ':') && $this->query->isBind(substr($val, 1))) {
@@ -115,9 +119,6 @@ abstract class Builder
$this->query->bind('__data__' . $key, $val, isset($bind[$key]) ? $bind[$key] : PDO::PARAM_STR); $this->query->bind('__data__' . $key, $val, isset($bind[$key]) ? $bind[$key] : PDO::PARAM_STR);
$result[$item] = ':__data__' . $key; $result[$item] = ':__data__' . $key;
} }
} elseif (is_object($val) && method_exists($val, '__toString')) {
// 对象数据写入
$result[$item] = $val->__toString();
} }
} }
return $result; return $result;
@@ -279,6 +280,13 @@ abstract class Builder
$whereStr .= empty($whereStr) ? substr(implode(' ', $str), strlen($key) + 1) : implode(' ', $str); $whereStr .= empty($whereStr) ? substr(implode(' ', $str), strlen($key) + 1) : implode(' ', $str);
} }
if (!empty($options['soft_delete'])) {
// 附加软删除条件
list($field, $condition) = $options['soft_delete'];
$whereStr = $whereStr ? '( ' . $whereStr . ' ) AND ' : '';
$whereStr = $whereStr . $this->parseWhereItem($field, $condition, '', $options, $binds);
}
return $whereStr; return $whereStr;
} }
@@ -379,7 +387,7 @@ abstract class Builder
} else { } else {
$zone = implode(',', $this->parseValue($value, $field)); $zone = implode(',', $this->parseValue($value, $field));
} }
$whereStr .= $key . ' ' . $exp . ' (' . $zone . ')'; $whereStr .= $key . ' ' . $exp . ' (' . (empty($zone) ? "''" : $zone) . ')';
} }
} elseif (in_array($exp, ['NOT BETWEEN', 'BETWEEN'])) { } elseif (in_array($exp, ['NOT BETWEEN', 'BETWEEN'])) {
// BETWEEN 查询 // BETWEEN 查询

View File

@@ -893,7 +893,7 @@ class Query
} else { } else {
$name = $alias . '.' . $key; $name = $alias . '.' . $key;
} }
$fields[] = $name . ' AS ' . $val; $fields[$name] = $val;
$this->options['map'][$val] = $name; $this->options['map'][$val] = $name;
} }
} }
@@ -1120,6 +1120,20 @@ class Query
return $this; return $this;
} }
/**
* 设置软删除字段及条件
* @access public
* @param false|string $field 查询字段
* @param mixed $condition 查询条件
* @return $this
*/
public function useSoftDelete($field, $condition = null)
{
if ($field) {
$this->options['soft_delete'] = [$field, $condition ?: ['null', '']];
}
}
/** /**
* 分析查询表达式 * 分析查询表达式
* @access public * @access public
@@ -1895,7 +1909,7 @@ class Query
$relation = Loader::parseName($relation, 1, false); $relation = Loader::parseName($relation, 1, false);
$model = $class->$relation(); $model = $class->$relation();
if ($model instanceof OneToOne && 0 == $model->getEagerlyType()) { if ($model instanceof OneToOne && 0 == $model->getEagerlyType()) {
$model->eagerly($this, $relation, $subRelation, $closure, $first); $model->removeOption()->eagerly($this, $relation, $subRelation, $closure, $first);
$first = false; $first = false;
} elseif ($closure) { } elseif ($closure) {
$with[$key] = $closure; $with[$key] = $closure;
@@ -2210,7 +2224,7 @@ class Query
// 执行操作 // 执行操作
$result = '' == $sql ? 0 : $this->execute($sql, $bind); $result = '' == $sql ? 0 : $this->execute($sql, $bind);
if ($result) { if ($result) {
if (isset($where[$pk])) { if (is_string($pk) && isset($where[$pk])) {
$data[$pk] = $where[$pk]; $data[$pk] = $where[$pk];
} elseif (is_string($pk) && isset($key) && strpos($key, '|')) { } elseif (is_string($pk) && isset($key) && strpos($key, '|')) {
list($a, $val) = explode('|', $key); list($a, $val) = explode('|', $key);
@@ -2302,7 +2316,7 @@ class Query
} }
} }
if (isset($cache)) { if (isset($cache) && $resultSet) {
// 缓存数据集 // 缓存数据集
$this->cacheData($key, $resultSet, $cache); $this->cacheData($key, $resultSet, $cache);
} }
@@ -2459,7 +2473,7 @@ class Query
$result = isset($resultSet[0]) ? $resultSet[0] : null; $result = isset($resultSet[0]) ? $resultSet[0] : null;
} }
if (isset($cache)) { if (isset($cache) && $result) {
// 缓存数据 // 缓存数据
$this->cacheData($key, $result, $cache); $this->cacheData($key, $result, $cache);
} }

View File

@@ -36,10 +36,11 @@ class Mysql extends Builder
$key = 'json_extract(' . $field . ', \'$.' . $name . '\')'; $key = 'json_extract(' . $field . ', \'$.' . $name . '\')';
} elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) { } elseif (strpos($key, '.') && !preg_match('/[,\'\"\(\)`\s]/', $key)) {
list($table, $key) = explode('.', $key, 2); list($table, $key) = explode('.', $key, 2);
if ('__TABLE__' == $table) {
$table = $this->query->getTable();
}
if (isset($options['alias'][$table])) { if (isset($options['alias'][$table])) {
$table = $options['alias'][$table]; $table = $options['alias'][$table];
} elseif ('__TABLE__' == $table) {
$table = $this->query->getTable();
} }
} }
if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) { if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {

View File

@@ -55,10 +55,11 @@ class Pgsql extends Builder
$key = $field . '->>\'' . $name . '\''; $key = $field . '->>\'' . $name . '\'';
} elseif (strpos($key, '.')) { } elseif (strpos($key, '.')) {
list($table, $key) = explode('.', $key, 2); list($table, $key) = explode('.', $key, 2);
if ('__TABLE__' == $table) {
$table = $this->query->getTable();
}
if (isset($options['alias'][$table])) { if (isset($options['alias'][$table])) {
$table = $options['alias'][$table]; $table = $options['alias'][$table];
} elseif ('__TABLE__' == $table) {
$table = $this->query->getTable();
} }
} }
if (isset($table)) { if (isset($table)) {

View File

@@ -60,10 +60,11 @@ class Sqlite extends Builder
$key = trim($key); $key = trim($key);
if (strpos($key, '.')) { if (strpos($key, '.')) {
list($table, $key) = explode('.', $key, 2); list($table, $key) = explode('.', $key, 2);
if ('__TABLE__' == $table) {
$table = $this->query->getTable();
}
if (isset($options['alias'][$table])) { if (isset($options['alias'][$table])) {
$table = $options['alias'][$table]; $table = $options['alias'][$table];
} elseif ('__TABLE__' == $table) {
$table = $this->query->getTable();
} }
} }
if (isset($table)) { if (isset($table)) {

View File

@@ -73,10 +73,11 @@ class Sqlsrv extends Builder
$key = trim($key); $key = trim($key);
if (strpos($key, '.') && !preg_match('/[,\'\"\(\)\[\s]/', $key)) { if (strpos($key, '.') && !preg_match('/[,\'\"\(\)\[\s]/', $key)) {
list($table, $key) = explode('.', $key, 2); list($table, $key) = explode('.', $key, 2);
if ('__TABLE__' == $table) {
$table = $this->query->getTable();
}
if (isset($options['alias'][$table])) { if (isset($options['alias'][$table])) {
$table = $options['alias'][$table]; $table = $options['alias'][$table];
} elseif ('__TABLE__' == $table) {
$table = $this->query->getTable();
} }
} }
if (!is_numeric($key) && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) { if (!is_numeric($key) && !preg_match('/[,\'\"\*\(\)\[.\s]/', $key)) {

View File

@@ -25,6 +25,8 @@ class File
'apart_level' => [], 'apart_level' => [],
]; ];
protected $writed = [];
// 实例化并传入参数 // 实例化并传入参数
public function __construct($config = []) public function __construct($config = [])
{ {
@@ -37,45 +39,17 @@ class File
* 日志写入接口 * 日志写入接口
* @access public * @access public
* @param array $log 日志信息 * @param array $log 日志信息
* @param bool $depr 是否写入分割线
* @return bool * @return bool
*/ */
public function save(array $log = [], $depr = true) public function save(array $log = [])
{ {
$now = date($this->config['time_format']); $cli = IS_CLI ? '_cli' : '';
$destination = $this->config['path'] . date('Ym') . DS . date('d') . '.log'; $destination = $this->config['path'] . date('Ym') . DS . date('d') . $cli . '.log';
$path = dirname($destination); $path = dirname($destination);
!is_dir($path) && mkdir($path, 0755, true); !is_dir($path) && mkdir($path, 0755, true);
//检测日志文件大小,超过配置大小则备份日志文件重新生成
if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) {
rename($destination, dirname($destination) . DS . $_SERVER['REQUEST_TIME'] . '-' . basename($destination));
}
$depr = $depr ? "---------------------------------------------------------------\r\n" : '';
$info = ''; $info = '';
if (App::$debug) {
// 获取基本信息
if (isset($_SERVER['HTTP_HOST'])) {
$current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
} else {
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
}
$runtime = round(microtime(true) - THINK_START_TIME, 10);
$reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞';
$time_str = ' [运行时间:' . number_format($runtime, 6) . 's][吞吐率:' . $reqs . 'req/s]';
$memory_use = number_format((memory_get_usage() - THINK_START_MEM) / 1024, 2);
$memory_str = ' [内存消耗:' . $memory_use . 'kb]';
$file_load = ' [文件加载:' . count(get_included_files()) . ']';
$info = '[ log ] ' . $current_uri . $time_str . $memory_str . $file_load . "\r\n";
$server = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '0.0.0.0';
$remote = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'CLI';
$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
}
foreach ($log as $type => $val) { foreach ($log as $type => $val) {
$level = ''; $level = '';
foreach ($val as $msg) { foreach ($val as $msg) {
@@ -86,16 +60,60 @@ class File
} }
if (in_array($type, $this->config['apart_level'])) { if (in_array($type, $this->config['apart_level'])) {
// 独立记录的日志级别 // 独立记录的日志级别
$filename = $path . DS . date('d') . '_' . $type . '.log'; $filename = $path . DS . date('d') . '_' . $type . $cli . '.log';
error_log("[{$now}] {$level}\r\n{$depr}", 3, $filename); $this->write($level, $filename, true);
} else { } else {
$info .= $level; $info .= $level;
} }
} }
if (App::$debug) { if ($info) {
$info = "{$server} {$remote} {$method} {$uri}\r\n" . $info; return $this->write($info, $destination);
} }
return error_log("[{$now}] {$info}\r\n{$depr}", 3, $destination); return true;
}
protected function write($message, $destination, $apart = false)
{
//检测日志文件大小,超过配置大小则备份日志文件重新生成
if (is_file($destination) && floor($this->config['file_size']) <= filesize($destination)) {
rename($destination, dirname($destination) . DS . $_SERVER['REQUEST_TIME'] . '-' . basename($destination));
$this->writed[$destination] = false;
}
if (empty($this->writed[$destination]) && !IS_CLI) {
if (App::$debug && !$apart) {
// 获取基本信息
if (isset($_SERVER['HTTP_HOST'])) {
$current_uri = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
} else {
$current_uri = "cmd:" . implode(' ', $_SERVER['argv']);
}
$runtime = round(microtime(true) - THINK_START_TIME, 10);
$reqs = $runtime > 0 ? number_format(1 / $runtime, 2) : '∞';
$time_str = ' [运行时间:' . number_format($runtime, 6) . 's][吞吐率:' . $reqs . 'req/s]';
$memory_use = number_format((memory_get_usage() - THINK_START_MEM) / 1024, 2);
$memory_str = ' [内存消耗:' . $memory_use . 'kb]';
$file_load = ' [文件加载:' . count(get_included_files()) . ']';
$message = '[ info ] ' . $current_uri . $time_str . $memory_str . $file_load . "\r\n" . $message;
}
$now = date($this->config['time_format']);
$server = isset($_SERVER['SERVER_ADDR']) ? $_SERVER['SERVER_ADDR'] : '0.0.0.0';
$remote = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '0.0.0.0';
$method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'CLI';
$uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
$message = "---------------------------------------------------------------\r\n[{$now}] {$server} {$remote} {$method} {$uri}\r\n" . $message;
$this->writed[$destination] = true;
}
if (IS_CLI) {
$now = date($this->config['time_format']);
$message = "[{$now}]" . $message;
}
return error_log($message, 3, $destination);
} }
} }

View File

@@ -16,13 +16,17 @@ use think\Model;
class Pivot extends Model class Pivot extends Model
{ {
/** @var Model */
public $parent;
/** /**
* 构造函数 * 构造函数
* @access public * @access public
* @param array|object $data 数据 * @param Model $parent
* @param string $table 中间数据表名 * @param array|object $data 数据
* @param string $table 中间数据表名
*/ */
public function __construct($data = [], $table = '') public function __construct(Model $parent, $data = [], $table = '')
{ {
if (is_object($data)) { if (is_object($data)) {
$this->data = get_object_vars($data); $this->data = get_object_vars($data);
@@ -30,6 +34,8 @@ class Pivot extends Model
$this->data = $data; $this->data = $data;
} }
$this->parent = $parent;
$this->table = $table; $this->table = $table;
} }

View File

@@ -91,7 +91,7 @@ abstract class Relation
} }
/** /**
* 执行基础查询(执行一次) * 执行基础查询(执行一次)
* @access protected * @access protected
* @return void * @return void
*/ */

View File

@@ -11,18 +11,23 @@
namespace think\model\relation; namespace think\model\relation;
use think\Collection;
use think\db\Query; use think\db\Query;
use think\Exception; use think\Exception;
use think\Loader; use think\Loader;
use think\Model; use think\Model;
use think\model\Pivot; use think\model\Pivot;
use think\model\Relation; use think\model\Relation;
use think\Paginator;
class BelongsToMany extends Relation class BelongsToMany extends Relation
{ {
// 中间表模型 // 中间表表名
protected $middle; protected $middle;
// 中间表模型
protected $pivot;
/** /**
* 构造函数 * 构造函数
* @access public * @access public
@@ -42,6 +47,64 @@ class BelongsToMany extends Relation
$this->query = (new $model)->db(); $this->query = (new $model)->db();
} }
/**
* 设置中间表模型
* @param $pivot
* @return $this
*/
public function pivot($pivot)
{
$this->pivot = $pivot;
return $this;
}
/**
* 实例化中间表模型
* @param $data
* @return mixed
*/
protected function newPivot($data)
{
$pivot = $this->pivot ?: '\\think\\model\\Pivot';
return new $pivot($this->parent, $data, $this->middle);
}
/**
* 合成中间表模型
* @param array|Collection|Paginator $models
*/
protected function hydratePivot($models)
{
foreach ($models as $model) {
$pivot = [];
foreach ($model->getData() as $key => $val) {
if (strpos($key, '__')) {
list($name, $attr) = explode('__', $key, 2);
if ('pivot' == $name) {
$pivot[$attr] = $val;
unset($model->$key);
}
}
}
$model->pivot = $this->newPivot($pivot);
}
}
/**
* 创建关联查询Query对象
* @return Query
*/
protected function buildQuery()
{
$foreignKey = $this->foreignKey;
$localKey = $this->localKey;
$middle = $this->middle;
// 关联查询
$pk = $this->parent->getPk();
$condition['pivot.' . $localKey] = $this->parent->$pk;
return $this->belongsToManyQuery($middle, $foreignKey, $localKey, $condition);
}
/** /**
* 延迟获取关联数据 * 延迟获取关联数据
* @param string $subRelation 子关联名 * @param string $subRelation 子关联名
@@ -50,32 +113,74 @@ class BelongsToMany extends Relation
*/ */
public function getRelation($subRelation = '', $closure = null) public function getRelation($subRelation = '', $closure = null)
{ {
$foreignKey = $this->foreignKey;
$localKey = $this->localKey;
$middle = $this->middle;
if ($closure) { if ($closure) {
call_user_func_array($closure, [ & $this->query]); call_user_func_array($closure, [& $this->query]);
}
// 关联查询
$pk = $this->parent->getPk();
$condition['pivot.' . $localKey] = $this->parent->$pk;
$result = $this->belongsToManyQuery($middle, $foreignKey, $localKey, $condition)->relation($subRelation)->select();
foreach ($result as $set) {
$pivot = [];
foreach ($set->getData() as $key => $val) {
if (strpos($key, '__')) {
list($name, $attr) = explode('__', $key, 2);
if ('pivot' == $name) {
$pivot[$attr] = $val;
unset($set->$key);
}
}
}
$set->pivot = new Pivot($pivot, $this->middle);
} }
$result = $this->buildQuery()->relation($subRelation)->select();
$this->hydratePivot($result);
return $result; return $result;
} }
/**
* 重载select方法
* @param null $data
* @return false|\PDOStatement|string|Collection
*/
public function select($data = null)
{
$result = $this->buildQuery()->select($data);
$this->hydratePivot($result);
return $result;
}
/**
* 重载paginate方法
* @param null $listRows
* @param bool $simple
* @param array $config
* @return Paginator
*/
public function paginate($listRows = null, $simple = false, $config = [])
{
$result = $this->buildQuery()->paginate($listRows, $simple, $config);
$this->hydratePivot($result);
return $result;
}
/**
* 重载find方法
* @param null $data
* @return array|false|\PDOStatement|string|Model
*/
public function find($data = null)
{
$result = $this->buildQuery()->find($data);
$this->hydratePivot([$result]);
return $result;
}
/**
* 查找多条记录 如果不存在则抛出异常
* @access public
* @param array|string|Query|\Closure $data
* @return array|\PDOStatement|string|Model
*/
public function selectOrFail($data = null)
{
return $this->failException(true)->select($data);
}
/**
* 查找单条记录 如果不存在则抛出异常
* @access public
* @param array|string|Query|\Closure $data
* @return array|\PDOStatement|string|Model
*/
public function findOrFail($data = null)
{
return $this->failException(true)->find($data);
}
/** /**
* 根据关联条件查询当前模型 * 根据关联条件查询当前模型
* @access public * @access public
@@ -95,12 +200,27 @@ class BelongsToMany extends Relation
* @access public * @access public
* @param mixed $where 查询条件(数组或者闭包) * @param mixed $where 查询条件(数组或者闭包)
* @return Query * @return Query
* @throws Exception
*/ */
public function hasWhere($where = []) public function hasWhere($where = [])
{ {
throw new Exception('relation not support: hasWhere'); throw new Exception('relation not support: hasWhere');
} }
/**
* 设置中间表的查询条件
* @param $field
* @param null $op
* @param null $condition
* @return $this
*/
public function wherePivot($field, $op = null, $condition = null)
{
$field = 'pivot.' . $field;
$this->query->where($field, $op, $condition);
return $this;
}
/** /**
* 预载入关联查询(数据集) * 预载入关联查询(数据集)
* @access public * @access public
@@ -230,7 +350,7 @@ class BelongsToMany extends Relation
} }
} }
} }
$set->pivot = new Pivot($pivot, $this->middle); $set->pivot = $this->newPivot($pivot);
$data[$pivot[$this->localKey]][] = $set; $data[$pivot[$this->localKey]][] = $set;
} }
return $data; return $data;
@@ -250,10 +370,14 @@ class BelongsToMany extends Relation
// 关联查询封装 // 关联查询封装
$tableName = $this->query->getTable(); $tableName = $this->query->getTable();
$relationFk = $this->query->getPk(); $relationFk = $this->query->getPk();
return $this->query->field($tableName . '.*') $query = $this->query->field($tableName . '.*')
->field(true, false, $table, 'pivot', 'pivot__') ->field(true, false, $table, 'pivot', 'pivot__');
->join($table . ' pivot', 'pivot.' . $foreignKey . '=' . $tableName . '.' . $relationFk)
->where($condition); if (empty($this->baseQuery)) {
$query->join($table . ' pivot', 'pivot.' . $foreignKey . '=' . $tableName . '.' . $relationFk)
->where($condition);
}
return $query;
} }
/** /**
@@ -327,7 +451,7 @@ class BelongsToMany extends Relation
foreach ($ids as $id) { foreach ($ids as $id) {
$pivot[$this->foreignKey] = $id; $pivot[$this->foreignKey] = $id;
$this->query->table($this->middle)->insert($pivot, true); $this->query->table($this->middle)->insert($pivot, true);
$result[] = new Pivot($pivot, $this->middle); $result[] = $this->newPivot($pivot);
} }
if (count($result) == 1) { if (count($result) == 1) {
// 返回中间表模型对象 // 返回中间表模型对象

View File

@@ -183,7 +183,7 @@ class HasMany extends Relation
* 保存(新增)当前关联数据对象 * 保存(新增)当前关联数据对象
* @access public * @access public
* @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键 * @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键
* @return integer * @return Model|false
*/ */
public function save($data) public function save($data)
{ {
@@ -191,9 +191,9 @@ class HasMany extends Relation
$data = $data->getData(); $data = $data->getData();
} }
// 保存关联表数据 // 保存关联表数据
$data[$this->foreignKey] = $this->parent->{$this->localKey};
$model = new $this->model; $model = new $this->model;
return $model->save($data); $data[$this->foreignKey] = $this->parent->{$this->localKey};
return $model->save($data) ? $model : false;
} }
/** /**

View File

@@ -215,7 +215,7 @@ class MorphMany extends Relation
* 保存(新增)当前关联数据对象 * 保存(新增)当前关联数据对象
* @access public * @access public
* @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键 * @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键
* @return integer * @return Model|false
*/ */
public function save($data) public function save($data)
{ {
@@ -225,10 +225,10 @@ class MorphMany extends Relation
// 保存关联表数据 // 保存关联表数据
$pk = $this->parent->getPk(); $pk = $this->parent->getPk();
$model = new $this->model;
$data[$this->morphKey] = $this->parent->$pk; $data[$this->morphKey] = $this->parent->$pk;
$data[$this->morphType] = $this->type; $data[$this->morphType] = $this->type;
$model = new $this->model; return $model->save($data) ? $model : false;
return $model->save($data);
} }
/** /**

View File

@@ -114,6 +114,16 @@ class MorphTo extends Relation
return $this; return $this;
} }
/**
* 移除关联查询参数
* @access public
* @return $this
*/
public function removeOption()
{
return $this;
}
/** /**
* 预载入关联查询 * 预载入关联查询
* @access public * @access public

View File

@@ -67,6 +67,7 @@ abstract class OneToOne extends Relation
$field = true; $field = true;
} }
$query->field($field, false, $table, $alias); $query->field($field, false, $table, $alias);
$field = null;
} }
// 预载入封装 // 预载入封装
@@ -82,7 +83,7 @@ abstract class OneToOne extends Relation
if ($closure) { if ($closure) {
// 执行闭包查询 // 执行闭包查询
call_user_func_array($closure, [& $query]); call_user_func_array($closure, [ & $query]);
// 使用withField指定获取关联的字段 // 使用withField指定获取关联的字段
// $query->where(['id'=>1])->withField('id,name'); // $query->where(['id'=>1])->withField('id,name');
if ($query->getOptions('with_field')) { if ($query->getOptions('with_field')) {
@@ -91,10 +92,8 @@ abstract class OneToOne extends Relation
} }
} elseif (isset($this->option['field'])) { } elseif (isset($this->option['field'])) {
$field = $this->option['field']; $field = $this->option['field'];
} else {
$field = true;
} }
$query->field($field, false, $joinTable, $joinAlias, $relation . '__'); $query->field(isset($field) ? $field : true, false, $joinTable, $joinAlias, $relation . '__');
} }
/** /**
@@ -163,17 +162,17 @@ abstract class OneToOne extends Relation
* 保存(新增)当前关联数据对象 * 保存(新增)当前关联数据对象
* @access public * @access public
* @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键 * @param mixed $data 数据 可以使用数组 关联模型对象 和 关联对象的主键
* @return integer * @return Model|false
*/ */
public function save($data) public function save($data)
{ {
if ($data instanceof Model) { if ($data instanceof Model) {
$data = $data->getData(); $data = $data->getData();
} }
$model = new $this->model;
// 保存关联表数据 // 保存关联表数据
$data[$this->foreignKey] = $this->parent->{$this->localKey}; $data[$this->foreignKey] = $this->parent->{$this->localKey};
$model = new $this->model; return $model->save($data) ? $model : false;
return $model->save($data);
} }
/** /**
@@ -195,7 +194,6 @@ abstract class OneToOne extends Relation
*/ */
public function getEagerlyType() public function getEagerlyType()
{ {
$this->removeOption();
return $this->eagerlyType; return $this->eagerlyType;
} }
@@ -290,7 +288,7 @@ abstract class OneToOne extends Relation
{ {
// 预载入关联查询 支持嵌套预载入 // 预载入关联查询 支持嵌套预载入
if ($closure) { if ($closure) {
call_user_func_array($closure, [& $model]); call_user_func_array($closure, [ & $model]);
if ($field = $model->getOptions('with_field')) { if ($field = $model->getOptions('with_field')) {
$model->field($field)->removeOption('with_field'); $model->field($field)->removeOption('with_field');
} }

View File

@@ -190,7 +190,7 @@ class TagLib
* @param boolean $close 是否为闭合标签 * @param boolean $close 是否为闭合标签
* @return string * @return string
*/ */
private function getRegex($tags, $close) public function getRegex($tags, $close)
{ {
$begin = $this->tpl->config('taglib_begin'); $begin = $this->tpl->config('taglib_begin');
$end = $this->tpl->config('taglib_end'); $end = $this->tpl->config('taglib_end');

View File

@@ -30,7 +30,7 @@ trait SoftDelete
{ {
$model = new static(); $model = new static();
$field = $model->getDeleteTimeField(true); $field = $model->getDeleteTimeField(true);
return $model->db(false)->removeWhereField($field); return $model->db(false);
} }
/** /**
@@ -42,7 +42,8 @@ trait SoftDelete
{ {
$model = new static(); $model = new static();
$field = $model->getDeleteTimeField(true); $field = $model->getDeleteTimeField(true);
return $model->db(false)->whereNotNull($field); return $model->db(false)
->useSoftDelete($field, ['not null', '']);
} }
/** /**
@@ -112,12 +113,14 @@ trait SoftDelete
{ {
$name = $this->getDeleteTimeField(); $name = $this->getDeleteTimeField();
if (empty($where)) { if (empty($where)) {
$pk = $this->getPk(); $pk = $this->getPk();
$where[$pk] = $this->getData($pk); $where[$pk] = $this->getData($pk);
$where[$name] = ['not null', ''];
} }
// 恢复删除 // 恢复删除
return $this->db(false)->removeWhereField($this->getDeleteTimeField(true))->where($where)->update([$name => null]); return $this->db(false)
->useSoftDelete($name, ['not null', ''])
->where($where)
->update([$name => null]);
} }
/** /**
@@ -129,7 +132,7 @@ trait SoftDelete
protected function base($query) protected function base($query)
{ {
$field = $this->getDeleteTimeField(true); $field = $this->getDeleteTimeField(true);
$query->whereNull($field); $query->useSoftDelete($field);
} }
/** /**