内核更新

bug修复
This commit is contained in:
2016-10-02 11:50:36 +08:00
parent 7608d4d0f7
commit a70c700b04
27 changed files with 201 additions and 141 deletions

View File

@@ -34,9 +34,6 @@ class User extends Base {
array('title' => '密码修改', 'url' => 'user/profile/editpw', 'icon' => 'key'), array('title' => '密码修改', 'url' => 'user/profile/editpw', 'icon' => 'key'),
array('title' => '更换头像', 'url' => 'user/profile/avatar', 'icon' => 'male'), array('title' => '更换头像', 'url' => 'user/profile/avatar', 'icon' => 'male'),
); );
$menu['订单管理'] = array(
array('title' => '我的订单', 'url' => 'user/order/index', 'icon' => 'shopping-bag'),
);
$contetnmenu = $this->getContentMenu(); $contetnmenu = $this->getContentMenu();
if (!empty($contetnmenu)) { if (!empty($contetnmenu)) {
$menu['内容管理'] = $contetnmenu; $menu['内容管理'] = $contetnmenu;

View File

@@ -73,7 +73,7 @@ class Document extends \think\model\Merge{
if (is_numeric($name)) { if (is_numeric($name)) {
$name = db('model')->where(array('id'=>$name))->value('name'); $name = db('model')->where(array('id'=>$name))->value('name');
} }
self::$relationModel = array('document_' . $name); $this->relationModel = array('document_' . $name);
return $this; return $this;
} }

View File

@@ -9,7 +9,7 @@
// | Author: liu21st <liu21st@gmail.com> // | Author: liu21st <liu21st@gmail.com>
// +---------------------------------------------------------------------- // +----------------------------------------------------------------------
define('THINK_VERSION', '5.0.0'); define('THINK_VERSION', '5.0.2dev');
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

@@ -79,6 +79,7 @@ class App
{ {
is_null($request) && $request = Request::instance(); is_null($request) && $request = Request::instance();
try {
$config = self::initCommon(); $config = self::initCommon();
if (defined('BIND_MODULE')) { if (defined('BIND_MODULE')) {
// 模块/控制器绑定 // 模块/控制器绑定
@@ -92,18 +93,20 @@ class App
} }
$request->filter($config['default_filter']); $request->filter($config['default_filter']);
try {
// 开启多语言机制
if ($config['lang_switch_on']) { if ($config['lang_switch_on']) {
// 获取当前语言 // 开启多语言机制 检测当前语言
$request->langset(Lang::detect()); Lang::detect();
} else {
// 读取默认语言
Lang::range($config['default_lang']);
}
$request->langset(Lang::range());
// 加载系统语言包 // 加载系统语言包
Lang::load(THINK_PATH . 'lang' . DS . $request->langset() . EXT); Lang::load([
if (!$config['app_multi_module']) { THINK_PATH . 'lang' . DS . $request->langset() . EXT,
Lang::load(APP_PATH . 'lang' . DS . $request->langset() . EXT); APP_PATH . 'lang' . DS . $request->langset() . EXT,
} ]);
}
// 获取应用调度信息 // 获取应用调度信息
$dispatch = self::$dispatch; $dispatch = self::$dispatch;
@@ -496,7 +499,7 @@ class App
} }
// 加载当前模块语言包 // 加载当前模块语言包
if ($config['lang_switch_on'] && $module) { if ($module) {
Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT); Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);
} }
} }

View File

@@ -40,7 +40,7 @@ use think\paginator\Collection as PaginatorCollection;
* @method boolean chunk(integer $count, callable $callback, string $column = null) static 分块获取数据 * @method boolean chunk(integer $count, callable $callback, string $column = null) static 分块获取数据
* @method mixed query(string $sql, array $bind = [], boolean $fetch = false, boolean $master = false, mixed $class = false) static SQL查询 * @method mixed query(string $sql, array $bind = [], boolean $fetch = false, boolean $master = false, mixed $class = false) static SQL查询
* @method integer execute(string $sql, array $bind = [], boolean $fetch = false, boolean $getLastInsID = false, string $sequence = null) static SQL执行 * @method integer execute(string $sql, array $bind = [], boolean $fetch = false, boolean $getLastInsID = false, string $sequence = null) static SQL执行
* @method PaginatorCollection paginate(integer $listRows = 15, boolean $simple = false, array $config = []) static 分页查询 * @method PaginatorCollection paginate(integer $listRows = 15, mixed $simple = false, array $config = []) static 分页查询
* @method mixed transaction(callable $callback) static 执行数据库事务 * @method mixed transaction(callable $callback) static 执行数据库事务
* @method boolean batchQuery(array $sqlArray) static 批处理执行SQL语句 * @method boolean batchQuery(array $sqlArray) static 批处理执行SQL语句
*/ */

View File

@@ -403,4 +403,9 @@ class File extends SplFileObject
{ {
return $this->error; return $this->error;
} }
public function __call($method, $args)
{
return $this->hash($method);
}
} }

View File

@@ -25,6 +25,8 @@ class Lang
protected static $langDetectVar = 'lang'; protected static $langDetectVar = 'lang';
// 语言Cookie变量 // 语言Cookie变量
protected static $langCookieVar = 'think_var'; protected static $langCookieVar = 'think_var';
// 语言Cookie的过期时间
protected static $langCookieExpire = 3600;
// 允许语言列表 // 允许语言列表
protected static $allowLangList = []; protected static $allowLangList = [];
@@ -81,11 +83,9 @@ class Lang
// 记录加载信息 // 记录加载信息
App::$debug && Log::record('[ LANG ] ' . $_file, 'info'); App::$debug && Log::record('[ LANG ] ' . $_file, 'info');
$_lang = include $_file; $_lang = include $_file;
} else {
$_lang = [];
}
$lang = array_change_key_case($_lang) + $lang; $lang = array_change_key_case($_lang) + $lang;
} }
}
if (!empty($lang)) { if (!empty($lang)) {
self::$lang[$range] = $lang + self::$lang[$range]; self::$lang[$range] = $lang + self::$lang[$range];
} }
@@ -157,7 +157,7 @@ class Lang
if (isset($_GET[self::$langDetectVar])) { if (isset($_GET[self::$langDetectVar])) {
// url中设置了语言变量 // url中设置了语言变量
$langSet = strtolower($_GET[self::$langDetectVar]); $langSet = strtolower($_GET[self::$langDetectVar]);
Cookie::set(self::$langCookieVar, $langSet, 3600); Cookie::set(self::$langCookieVar, $langSet, self::$langCookieExpire);
} elseif (Cookie::get(self::$langCookieVar)) { } elseif (Cookie::get(self::$langCookieVar)) {
// 获取上次用户的选择 // 获取上次用户的选择
$langSet = strtolower(Cookie::get(self::$langCookieVar)); $langSet = strtolower(Cookie::get(self::$langCookieVar));
@@ -165,7 +165,7 @@ class Lang
// 自动侦测浏览器语言 // 自动侦测浏览器语言
preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches); preg_match('/^([a-z\d\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
$langSet = strtolower($matches[1]); $langSet = strtolower($matches[1]);
Cookie::set(self::$langCookieVar, $langSet, 3600); Cookie::set(self::$langCookieVar, $langSet, self::$langCookieExpire);
} }
if (empty(self::$allowLangList) || in_array($langSet, self::$allowLangList)) { if (empty(self::$allowLangList) || in_array($langSet, self::$allowLangList)) {
// 合法的语言 // 合法的语言
@@ -197,6 +197,16 @@ class Lang
self::$langCookieVar = $var; self::$langCookieVar = $var;
} }
/**
* 设置语言的cookie的过期时间
* @param string $expire 过期时间
* @return void
*/
public static function setLangCookieExpire($expire)
{
self::$langCookieExpire = $expire;
}
/** /**
* 设置允许的语言列表 * 设置允许的语言列表
* @param array $list 语言列表 * @param array $list 语言列表

View File

@@ -322,7 +322,7 @@ class Loader
//加载当前模块应用类库 //加载当前模块应用类库
$baseUrl = App::$modulePath; $baseUrl = App::$modulePath;
} elseif (is_dir(EXTEND_PATH . $name)) { } elseif (is_dir(EXTEND_PATH . $name)) {
$baseUrl = EXTEND_PATH; $baseUrl = EXTEND_PATH . $name . DS;
} else { } else {
// 加载其它模块的类库 // 加载其它模块的类库
$baseUrl = APP_PATH . $name . DS; $baseUrl = APP_PATH . $name . DS;

View File

@@ -13,6 +13,7 @@ namespace think;
use InvalidArgumentException; use InvalidArgumentException;
use think\Cache; use think\Cache;
use think\Config;
use think\Db; use think\Db;
use think\db\Query; use think\db\Query;
use think\Exception; use think\Exception;
@@ -99,7 +100,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 验证失败是否抛出异常 // 验证失败是否抛出异常
protected $failException = false; protected $failException = false;
// 全局查询范围 // 全局查询范围
protected static $useGlobalScope = true; protected $useGlobalScope = true;
/** /**
* 初始化过的模型. * 初始化过的模型.
@@ -126,7 +127,12 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
if (empty($this->name)) { if (empty($this->name)) {
// 当前模型名 // 当前模型名
$this->name = basename(str_replace('\\', '/', $this->class)); $name = str_replace('\\', '/', $this->class);
$this->name = basename($name);
if (Config::get('class_suffix')) {
$suffix = basename(dirname($name));
$this->name = substr($this->name, 0, -strlen($suffix));
}
} }
if (is_null($this->autoWriteTimestamp)) { if (is_null($this->autoWriteTimestamp)) {
@@ -141,9 +147,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
/** /**
* 获取当前模型的数据库查询对象 * 获取当前模型的数据库查询对象
* @access public * @access public
* @param bool $baseQuery 是否调用全局查询范围
* @return Query * @return Query
*/ */
public function db() public function db($baseQuery = true)
{ {
$model = $this->class; $model = $this->class;
if (!isset(self::$links[$model])) { if (!isset(self::$links[$model])) {
@@ -163,6 +170,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
self::$links[$model] = $query; self::$links[$model] = $query;
} }
// 全局作用域
if ($baseQuery && method_exists($this, 'base')) {
call_user_func_array([$this, 'base'], [ & self::$links[$model]]);
}
// 返回当前模型的数据库查询对象 // 返回当前模型的数据库查询对象
return self::$links[$model]; return self::$links[$model];
} }
@@ -401,9 +412,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
// 类型转换 // 类型转换
$value = $this->readTransform($value, $this->type[$name]); $value = $this->readTransform($value, $this->type[$name]);
} elseif ($notFound) { } elseif ($notFound) {
if (method_exists($this, $name) && !method_exists('\think\Model', $name)) { $method = Loader::parseName($name, 1);
if (method_exists($this, $method) && !method_exists('\think\Model', $method)) {
// 不存在该字段 获取关联数据 // 不存在该字段 获取关联数据
$value = $this->relation()->getRelation($name); $value = $this->relation()->getRelation($method);
// 保存关联对象值 // 保存关联对象值
$this->data[$name] = $value; $this->data[$name] = $value;
} else { } else {
@@ -1110,7 +1122,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public static function useGlobalScope($use) public static function useGlobalScope($use)
{ {
$model = new static(); $model = new static();
static::$useGlobalScope = $use; $model->useGlobalScope = $use;
return $model; return $model;
} }
@@ -1333,10 +1345,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public function __call($method, $args) public function __call($method, $args)
{ {
$query = $this->db(); $query = $this->db();
// 全局作用域
if (static::$useGlobalScope && method_exists($this, 'base')) {
call_user_func_array('static::base', [ & $query]);
}
if (method_exists($this, 'scope' . $method)) { if (method_exists($this, 'scope' . $method)) {
// 动态调用命名范围 // 动态调用命名范围
$method = 'scope' . $method; $method = 'scope' . $method;
@@ -1351,11 +1359,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess
public static function __callStatic($method, $params) public static function __callStatic($method, $params)
{ {
$query = self::getDb(); $query = self::getDb();
$model = get_called_class();
// 全局作用域
if (static::$useGlobalScope && method_exists($model, 'base')) {
call_user_func_array('static::base', [ & $query]);
}
return call_user_func_array([$query, $method], $params); return call_user_func_array([$query, $method], $params);
} }

View File

@@ -1476,6 +1476,7 @@ class Request
*/ */
public function cache($key, $expire = null) public function cache($key, $expire = null)
{ {
if ($this->isGet()) {
if (false !== strpos($key, ':')) { if (false !== strpos($key, ':')) {
$param = $this->param(); $param = $this->param();
foreach ($param as $item => $val) { foreach ($param as $item => $val) {
@@ -1483,18 +1484,31 @@ class Request
$key = str_replace(':' . $item, $val, $key); $key = str_replace(':' . $item, $val, $key);
} }
} }
} elseif ('__URL__' == $key) {
// 当前URL地址作为缓存标识
$key = md5($this->url());
} elseif (strpos($key, ']')) {
if ('[' . $this->ext() . ']' == $key) {
// 缓存某个后缀的请求
$key = md5($this->url());
} else {
return;
} }
if (Cache::has($key)) { }
if (strtotime($this->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $_SERVER['REQUEST_TIME']) {
// 读取缓存 // 读取缓存
$content = Cache::get($key); $response = Response::create()->code(304);
$response = Response::create($content) throw new \think\exception\HttpResponseException($response);
->code(304) } elseif (Cache::has($key)) {
->header('Content-Type', Cache::get($key . '_header')); list($content, $header) = Cache::get($key);
$response = Response::create($content)->header($header);
throw new \think\exception\HttpResponseException($response); throw new \think\exception\HttpResponseException($response);
} else { } else {
$this->cache = [$key, $expire]; $this->cache = [$key, $expire];
} }
} }
}
/** /**
* 读取缓存设置 * 读取缓存设置

View File

@@ -111,15 +111,17 @@ class Response
header($name . ':' . $val); header($name . ':' . $val);
} }
} }
echo $data;
if (200 == $this->code) { if (200 == $this->code) {
$cache = Request::instance()->getCache(); $cache = Request::instance()->getCache();
if ($cache) { if ($cache) {
Cache::set($cache[0], $data, $cache[1]); header('Cache-Control: max-age=' . $cache[1] . ',must-revalidate');
Cache::set($cache[0] . '_header', $this->header['Content-Type']); header('Last-Modified:' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Expires:' . gmdate('D, d M Y H:i:s', $_SERVER['REQUEST_TIME'] + $cache[1]) . ' GMT');
$header['Content-Type'] = $this->header['Content-Type'];
Cache::set($cache[0], [$data, $header], $cache[1]);
} }
} }
echo $data;
if (function_exists('fastcgi_finish_request')) { if (function_exists('fastcgi_finish_request')) {
// 提高页面响应 // 提高页面响应

View File

@@ -830,7 +830,7 @@ class Route
if (true === $rule) { if (true === $rule) {
$rule = self::getRouteExpress($url); $rule = self::getRouteExpress($url);
} }
if (!empty($rule['route'])) { if (!empty($rule['route']) && self::checkOption($rule['option'], $url, $request)) {
return self::parseRule($url, $rule['route'], $url, $rule['option']); return self::parseRule($url, $rule['route'], $url, $rule['option']);
} }
} }

View File

@@ -977,14 +977,14 @@ class Template
break; break;
case 'COOKIE': case 'COOKIE':
if (isset($vars[2])) { if (isset($vars[2])) {
$parseStr = '$_COOKIE[\'' . $vars[1] . '\'][\'' . $vars[2] . '\']'; $parseStr = '\\think\\Cookie::get(\'' . $vars[1] . '.' . $vars[2] . '\')';
} else { } else {
$parseStr = '\\think\\Cookie::get(\'' . $vars[1] . '\')'; $parseStr = '\\think\\Cookie::get(\'' . $vars[1] . '\')';
} }
break; break;
case 'SESSION': case 'SESSION':
if (isset($vars[2])) { if (isset($vars[2])) {
$parseStr = '$_SESSION[\'' . $vars[1] . '\'][\'' . $vars[2] . '\']'; $parseStr = '\\think\\Session::get(\'' . $vars[1] . '.' . $vars[2] . '\')';
} else { } else {
$parseStr = '\\think\\Session::get(\'' . $vars[1] . '\')'; $parseStr = '\\think\\Session::get(\'' . $vars[1] . '\')';
} }

View File

@@ -16,6 +16,7 @@ namespace think\cache;
*/ */
abstract class Driver abstract class Driver
{ {
protected $handler = null;
protected $options = []; protected $options = [];
protected $tag; protected $tag;
@@ -173,4 +174,15 @@ abstract class Driver
return []; return [];
} }
} }
/**
* 返回句柄对象,可执行其它高级方法
*
* @access public
* @return object
*/
public function handler()
{
return $this->handler;
}
} }

View File

@@ -221,9 +221,13 @@ class File extends Driver
$this->rm('tag_' . md5($tag)); $this->rm('tag_' . md5($tag));
return true; return true;
} }
$fileLsit = (array) glob($this->options['path'] . '*'); $files = (array) glob($this->options['path'] . ($this->options['prefix'] ? $this->options['prefix'] . DS : '') . '*');
foreach ($fileLsit as $path) { foreach ($files as $path) {
is_file($path) && unlink($path); if (is_dir($path)) {
array_map('unlink', glob($path . '/*.php'));
} else {
unlink($path);
}
} }
return true; return true;
} }

View File

@@ -180,6 +180,6 @@ class Lite extends Driver
$this->rm('tag_' . md5($tag)); $this->rm('tag_' . md5($tag));
return true; return true;
} }
array_map("unlink", glob($this->options['path'] . $this->options['prefix'] . '*.php')); array_map("unlink", glob($this->options['path'] . ($this->options['prefix'] ? $this->options['prefix'] . DS : '') . '*.php'));
} }
} }

View File

@@ -16,7 +16,6 @@ use think\Exception;
class Memcache extends Driver class Memcache extends Driver
{ {
protected $handler = null;
protected $options = [ protected $options = [
'host' => '127.0.0.1', 'host' => '127.0.0.1',
'port' => 11211, 'port' => 11211,

View File

@@ -15,7 +15,6 @@ use think\cache\Driver;
class Memcached extends Driver class Memcached extends Driver
{ {
protected $handler;
protected $options = [ protected $options = [
'host' => '127.0.0.1', 'host' => '127.0.0.1',
'port' => 11211, 'port' => 11211,

View File

@@ -22,7 +22,6 @@ use think\cache\Driver;
*/ */
class Redis extends Driver class Redis extends Driver
{ {
protected $handler = null;
protected $options = [ protected $options = [
'host' => '127.0.0.1', 'host' => '127.0.0.1',
'port' => 6379, 'port' => 6379,
@@ -174,14 +173,4 @@ class Redis extends Driver
return $this->handler->flushDB(); return $this->handler->flushDB();
} }
/**
* 返回句柄对象,可执行其它高级方法
*
* @access public
* @return object
*/
public function handler()
{
return $this->handler;
}
} }

View File

@@ -20,7 +20,6 @@ use think\Exception;
*/ */
class Sqlite extends Driver class Sqlite extends Driver
{ {
protected $options = [ protected $options = [
'db' => ':memory:', 'db' => ':memory:',
'table' => 'sharedmemory', 'table' => 'sharedmemory',

View File

@@ -25,8 +25,6 @@ class Wincache extends Driver
'expire' => 0, 'expire' => 0,
]; ];
protected $tag;
/** /**
* 架构函数 * 架构函数
* @param array $options 缓存参数 * @param array $options 缓存参数

View File

@@ -489,51 +489,51 @@ class Query
*/ */
public function count($field = '*') public function count($field = '*')
{ {
return $this->value('COUNT(' . $field . ') AS tp_count', 0); return (int) $this->value('COUNT(' . $field . ') AS tp_count', 0);
} }
/** /**
* SUM查询 * SUM查询
* @access public * @access public
* @param string $field 字段名 * @param string $field 字段名
* @return integer * @return float|int
*/ */
public function sum($field = '*') public function sum($field = '*')
{ {
return $this->value('SUM(' . $field . ') AS tp_sum', 0); return $this->value('SUM(' . $field . ') AS tp_sum', 0) + 0;
} }
/** /**
* MIN查询 * MIN查询
* @access public * @access public
* @param string $field 字段名 * @param string $field 字段名
* @return integer * @return float|int
*/ */
public function min($field = '*') public function min($field = '*')
{ {
return $this->value('MIN(' . $field . ') AS tp_min', 0); return $this->value('MIN(' . $field . ') AS tp_min', 0) + 0;
} }
/** /**
* MAX查询 * MAX查询
* @access public * @access public
* @param string $field 字段名 * @param string $field 字段名
* @return integer * @return float|int
*/ */
public function max($field = '*') public function max($field = '*')
{ {
return $this->value('MAX(' . $field . ') AS tp_max', 0); return $this->value('MAX(' . $field . ') AS tp_max', 0) + 0;
} }
/** /**
* AVG查询 * AVG查询
* @access public * @access public
* @param string $field 字段名 * @param string $field 字段名
* @return integer * @return float|int
*/ */
public function avg($field = '*') public function avg($field = '*')
{ {
return $this->value('AVG(' . $field . ') AS tp_avg', 0); return $this->value('AVG(' . $field . ') AS tp_avg', 0) + 0;
} }
/** /**
@@ -972,7 +972,7 @@ class Query
/** /**
* 分页查询 * 分页查询
* @param int|null $listRows 每页数量 * @param int|null $listRows 每页数量
* @param bool $simple 简洁模式 * @param int|bool $simple 简洁模式或者总记录数
* @param array $config 配置参数 * @param array $config 配置参数
* page:当前页, * page:当前页,
* path:url路径, * path:url路径,
@@ -986,6 +986,10 @@ class Query
*/ */
public function paginate($listRows = null, $simple = false, $config = []) public function paginate($listRows = null, $simple = false, $config = [])
{ {
if (is_int($simple)) {
$total = $simple;
$simple = false;
}
$config = array_merge(Config::get('paginate'), $config); $config = array_merge(Config::get('paginate'), $config);
$listRows = $listRows ?: $config['list_rows']; $listRows = $listRows ?: $config['list_rows'];
@@ -1000,16 +1004,17 @@ class Query
$config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class, 'getCurrentPath']); $config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class, 'getCurrentPath']);
if (!$simple) { if (!isset($total) && !$simple) {
$options = $this->getOptions(); $options = $this->getOptions();
$total = $this->count(); $total = $this->count();
$bind = $this->bind; $bind = $this->bind;
$results = $this->options($options)->bind($bind)->page($page, $listRows)->select(); $results = $this->options($options)->bind($bind)->page($page, $listRows)->select();
} else { } elseif ($simple) {
$results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select(); $results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select();
$total = null; $total = null;
} else {
$results = $this->page($page, $listRows)->select();
} }
return $class::make($results, $listRows, $page, $total, $simple, $config); return $class::make($results, $listRows, $page, $total, $simple, $config);
} }
@@ -1482,7 +1487,11 @@ class Query
*/ */
public function getOptions($name = '') public function getOptions($name = '')
{ {
return isset($this->options[$name]) ? $this->options[$name] : $this->options; if ('' === $name) {
return $this->options;
} else {
return isset($this->options[$name]) ? $this->options[$name] : null;
}
} }
/** /**

View File

@@ -32,7 +32,7 @@ class Mysql extends Builder
if (strpos($key, '$.') && false === strpos($key, '(')) { if (strpos($key, '$.') && false === strpos($key, '(')) {
// JSON字段支持 // JSON字段支持
list($field, $name) = explode('$.', $key); list($field, $name) = explode('$.', $key);
$key = 'jsn_extract(' . $field . ', \'$.\'.' . $name . ')'; $key = 'json_extract(' . $field . ', \'$.' . $name . '\')';
} }
if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) { if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) {
$key = '`' . $key . '`'; $key = '`' . $key . '`';

View File

@@ -203,10 +203,6 @@ class Handle
if (IS_CLI) { if (IS_CLI) {
return $message; return $message;
} }
// 导入语言包
if (!Config::get('lang_switch_on')) {
Lang::load(THINK_PATH . 'lang' . DS . Lang::detect() . EXT);
}
if (strpos($message, ':')) { if (strpos($message, ':')) {
$name = strstr($message, ':', true); $name = strstr($message, ':', true);

View File

@@ -17,7 +17,7 @@ use think\Model;
class Merge extends Model class Merge extends Model
{ {
protected static $relationModel = []; // HAS ONE 关联的模型列表 protected $relationModel = []; // HAS ONE 关联的模型列表
protected $fk = ''; // 外键名 默认为主表名_id protected $fk = ''; // 外键名 默认为主表名_id
protected $mapFields = []; // 需要处理的模型映射字段,避免混淆 array( id => 'user.id' ) protected $mapFields = []; // 需要处理的模型映射字段,避免混淆 array( id => 'user.id' )
@@ -64,7 +64,7 @@ class Merge extends Model
$fields = self::getModelField($query, $master, '', $class->mapFields); $fields = self::getModelField($query, $master, '', $class->mapFields);
$query->alias($master)->field($fields); $query->alias($master)->field($fields);
foreach (static::$relationModel as $key => $model) { foreach ($class->relationModel as $key => $model) {
$name = is_int($key) ? $model : $key; $name = is_int($key) ? $model : $key;
$table = is_int($key) ? $query->getTable($name) : $model; $table = is_int($key) ? $query->getTable($name) : $model;
$query->join($table . ' ' . $name, $name . '.' . $class->fk . '=' . $master . '.' . $class->getPk()); $query->join($table . ' ' . $name, $name . '.' . $class->fk . '=' . $master . '.' . $class->getPk());
@@ -126,7 +126,7 @@ class Merge extends Model
$item = []; $item = [];
foreach ($data as $key => $val) { foreach ($data as $key => $val) {
if ($insert || in_array($key, $this->change) || $this->isPk($key)) { if ($insert || in_array($key, $this->change) || $this->isPk($key)) {
if (array_key_exists($key, $this->mapFields)) { if ($this->fk != $key && array_key_exists($key, $this->mapFields)) {
list($name, $key) = explode('.', $this->mapFields[$key]); list($name, $key) = explode('.', $this->mapFields[$key]);
if ($model == $name) { if ($model == $name) {
$item[$key] = $val; $item[$key] = $val;
@@ -203,7 +203,7 @@ class Merge extends Model
$result = $db->strict(false)->where($where)->update($data); $result = $db->strict(false)->where($where)->update($data);
// 写入附表数据 // 写入附表数据
foreach (static::$relationModel as $key => $model) { foreach ($this->relationModel as $key => $model) {
$name = is_int($key) ? $model : $key; $name = is_int($key) ? $model : $key;
$table = is_int($key) ? $db->getTable($model) : $model; $table = is_int($key) ? $db->getTable($model) : $model;
// 处理关联模型数据 // 处理关联模型数据
@@ -213,6 +213,8 @@ class Merge extends Model
$result = 1; $result = 1;
} }
} }
// 清空change
$this->change = [];
// 新增回调 // 新增回调
$this->trigger('after_update', $this); $this->trigger('after_update', $this);
} else { } else {
@@ -239,16 +241,19 @@ class Merge extends Model
if ($insertId) { if ($insertId) {
if (is_string($pk)) { if (is_string($pk)) {
$this->data[$pk] = $insertId; $this->data[$pk] = $insertId;
if ($this->fk == $pk) {
$this->change[] = $pk;
}
} }
$this->data[$this->fk] = $insertId; $this->data[$this->fk] = $insertId;
} }
// 写入附表数据 // 写入附表数据
$source = $this->data; $source = $this->data;
if ($insertId && is_string($pk) && isset($source[$pk])) { if ($insertId && is_string($pk) && isset($source[$pk]) && $this->fk != $pk) {
unset($source[$pk]); unset($source[$pk]);
} }
foreach (static::$relationModel as $key => $model) { foreach ($this->relationModel as $key => $model) {
$name = is_int($key) ? $model : $key; $name = is_int($key) ? $model : $key;
$table = is_int($key) ? $db->getTable($model) : $model; $table = is_int($key) ? $db->getTable($model) : $model;
// 处理关联模型数据 // 处理关联模型数据
@@ -257,6 +262,10 @@ class Merge extends Model
$query->table($table)->strict(false)->insert($data); $query->table($table)->strict(false)->insert($data);
} }
} }
// 标记为更新
$this->isUpdate = true;
// 清空change
$this->change = [];
// 新增回调 // 新增回调
$this->trigger('after_insert', $this); $this->trigger('after_insert', $this);
} }
@@ -288,7 +297,7 @@ class Merge extends Model
$pk = $this->data[$this->getPk()]; $pk = $this->data[$this->getPk()];
// 删除关联数据 // 删除关联数据
foreach (static::$relationModel as $key => $model) { foreach ($this->relationModel as $key => $model) {
$table = is_int($key) ? $db->getTable($model) : $model; $table = is_int($key) ? $db->getTable($model) : $model;
$query = clone $db; $query = clone $db;
$query->table($table)->where($this->fk, $pk)->delete(); $query->table($table)->where($this->fk, $pk)->delete();

View File

@@ -318,11 +318,7 @@ class Relation
} }
} }
if (!isset($list[$relation])) { $result->setAttr($relation, !isset($list[$relation]) ? null : (new $model($list[$relation]))->isUpdate(true));
// 设置关联模型属性
$list[$relation] = [];
}
$result->setAttr($relation, (new $model($list[$relation]))->isUpdate(true));
} }
/** /**

View File

@@ -12,7 +12,8 @@ trait SoftDelete
*/ */
public function trashed() public function trashed()
{ {
if (!empty($this->data[static::$deleteTime])) { $field = $this->getDeleteTimeField();
if (!empty($this->data[$field])) {
return true; return true;
} }
return false; return false;
@@ -37,7 +38,8 @@ trait SoftDelete
public static function onlyTrashed() public static function onlyTrashed()
{ {
$model = new static(); $model = new static();
return $model->db()->where(static::$deleteTime, 'exp', 'is not null'); $field = $model->getDeleteTimeField();
return $model->db()->where($field, 'exp', 'is not null');
} }
/** /**
@@ -51,10 +53,9 @@ trait SoftDelete
if (false === $this->trigger('before_delete', $this)) { if (false === $this->trigger('before_delete', $this)) {
return false; return false;
} }
$name = $this->getDeleteTimeField();
if (static::$deleteTime && !$force) { if (!$force) {
// 软删除 // 软删除
$name = static::$deleteTime;
$this->change[] = $name; $this->change[] = $name;
$this->data[$name] = $this->autoWriteTimestamp($name); $this->data[$name] = $this->autoWriteTimestamp($name);
$result = $this->isUpdate()->save(); $result = $this->isUpdate()->save();
@@ -106,12 +107,10 @@ trait SoftDelete
*/ */
public function restore($where = []) public function restore($where = [])
{ {
if (static::$deleteTime) { $name = $this->getDeleteTimeField();
// 恢复删除 // 恢复删除
$name = static::$deleteTime;
return $this->isUpdate()->save([$name => null], $where); return $this->isUpdate()->save([$name => null], $where);
}
return false;
} }
/** /**
@@ -120,11 +119,28 @@ trait SoftDelete
* @param \think\db\Query $query 查询对象 * @param \think\db\Query $query 查询对象
* @return void * @return void
*/ */
protected static function base($query) protected function base($query)
{ {
if (static::$deleteTime) { $field = $this->getDeleteTimeField(true);
$query->where(static::$deleteTime, 'null'); $query->where($field, 'null');
}
} }
/**
* 获取软删除字段
* @access public
* @param bool $read 是否查询操作 写操作的时候会自动去掉表别名
* @return string
*/
protected function getDeleteTimeField($read = false)
{
if (isset($this->deleteTime)) {
$field = $this->deleteTime;
} else {
$field = 'delete_time';
}
if (!$read && strpos($field, '.')) {
list($alias, $field) = explode('.', $field);
}
return $field;
}
} }