diff --git a/application/common/controller/User.php b/application/common/controller/User.php index 369d2956..0cc5d846 100644 --- a/application/common/controller/User.php +++ b/application/common/controller/User.php @@ -34,9 +34,6 @@ class User extends Base { array('title' => '密码修改', 'url' => 'user/profile/editpw', 'icon' => 'key'), array('title' => '更换头像', 'url' => 'user/profile/avatar', 'icon' => 'male'), ); - $menu['订单管理'] = array( - array('title' => '我的订单', 'url' => 'user/order/index', 'icon' => 'shopping-bag'), - ); $contetnmenu = $this->getContentMenu(); if (!empty($contetnmenu)) { $menu['内容管理'] = $contetnmenu; diff --git a/application/common/model/Document.php b/application/common/model/Document.php index 5e54210c..6b6767bf 100644 --- a/application/common/model/Document.php +++ b/application/common/model/Document.php @@ -73,7 +73,7 @@ class Document extends \think\model\Merge{ if (is_numeric($name)) { $name = db('model')->where(array('id'=>$name))->value('name'); } - self::$relationModel = array('document_' . $name); + $this->relationModel = array('document_' . $name); return $this; } diff --git a/core/base.php b/core/base.php index dcbeec7f..41afa489 100644 --- a/core/base.php +++ b/core/base.php @@ -9,7 +9,7 @@ // | Author: liu21st // +---------------------------------------------------------------------- -define('THINK_VERSION', '5.0.0'); +define('THINK_VERSION', '5.0.2dev'); define('THINK_START_TIME', microtime(true)); define('THINK_START_MEM', memory_get_usage()); define('EXT', '.php'); diff --git a/core/library/think/App.php b/core/library/think/App.php index 92eb59fa..7e140ca9 100644 --- a/core/library/think/App.php +++ b/core/library/think/App.php @@ -79,32 +79,35 @@ class App { is_null($request) && $request = Request::instance(); - $config = self::initCommon(); - if (defined('BIND_MODULE')) { - // 模块/控制器绑定 - BIND_MODULE && Route::bind(BIND_MODULE); - } elseif ($config['auto_bind_module']) { - // 入口自动绑定 - $name = pathinfo($request->baseFile(), PATHINFO_FILENAME); - if ($name && 'index' != $name && is_dir(APP_PATH . $name)) { - Route::bind($name); - } - } - - $request->filter($config['default_filter']); try { - - // 开启多语言机制 - if ($config['lang_switch_on']) { - // 获取当前语言 - $request->langset(Lang::detect()); - // 加载系统语言包 - Lang::load(THINK_PATH . 'lang' . DS . $request->langset() . EXT); - if (!$config['app_multi_module']) { - Lang::load(APP_PATH . 'lang' . DS . $request->langset() . EXT); + $config = self::initCommon(); + if (defined('BIND_MODULE')) { + // 模块/控制器绑定 + BIND_MODULE && Route::bind(BIND_MODULE); + } elseif ($config['auto_bind_module']) { + // 入口自动绑定 + $name = pathinfo($request->baseFile(), PATHINFO_FILENAME); + if ($name && 'index' != $name && is_dir(APP_PATH . $name)) { + Route::bind($name); } } + $request->filter($config['default_filter']); + + if ($config['lang_switch_on']) { + // 开启多语言机制 检测当前语言 + Lang::detect(); + } else { + // 读取默认语言 + Lang::range($config['default_lang']); + } + $request->langset(Lang::range()); + // 加载系统语言包 + Lang::load([ + THINK_PATH . 'lang' . DS . $request->langset() . EXT, + APP_PATH . 'lang' . DS . $request->langset() . EXT, + ]); + // 获取应用调度信息 $dispatch = self::$dispatch; if (empty($dispatch)) { @@ -496,7 +499,7 @@ class App } // 加载当前模块语言包 - if ($config['lang_switch_on'] && $module) { + if ($module) { Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT); } } diff --git a/core/library/think/Db.php b/core/library/think/Db.php index e9a698d5..b00aee61 100644 --- a/core/library/think/Db.php +++ b/core/library/think/Db.php @@ -40,7 +40,7 @@ use think\paginator\Collection as PaginatorCollection; * @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 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 boolean batchQuery(array $sqlArray) static 批处理执行SQL语句 */ diff --git a/core/library/think/File.php b/core/library/think/File.php index 970063b2..43f38575 100644 --- a/core/library/think/File.php +++ b/core/library/think/File.php @@ -403,4 +403,9 @@ class File extends SplFileObject { return $this->error; } + + public function __call($method, $args) + { + return $this->hash($method); + } } diff --git a/core/library/think/Lang.php b/core/library/think/Lang.php index 4530b62a..16e7f545 100644 --- a/core/library/think/Lang.php +++ b/core/library/think/Lang.php @@ -25,6 +25,8 @@ class Lang protected static $langDetectVar = 'lang'; // 语言Cookie变量 protected static $langCookieVar = 'think_var'; + // 语言Cookie的过期时间 + protected static $langCookieExpire = 3600; // 允许语言列表 protected static $allowLangList = []; @@ -81,10 +83,8 @@ class Lang // 记录加载信息 App::$debug && Log::record('[ LANG ] ' . $_file, 'info'); $_lang = include $_file; - } else { - $_lang = []; + $lang = array_change_key_case($_lang) + $lang; } - $lang = array_change_key_case($_lang) + $lang; } if (!empty($lang)) { self::$lang[$range] = $lang + self::$lang[$range]; @@ -157,7 +157,7 @@ class Lang if (isset($_GET[self::$langDetectVar])) { // url中设置了语言变量 $langSet = strtolower($_GET[self::$langDetectVar]); - Cookie::set(self::$langCookieVar, $langSet, 3600); + Cookie::set(self::$langCookieVar, $langSet, self::$langCookieExpire); } elseif (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); $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)) { // 合法的语言 @@ -197,6 +197,16 @@ class Lang self::$langCookieVar = $var; } + /** + * 设置语言的cookie的过期时间 + * @param string $expire 过期时间 + * @return void + */ + public static function setLangCookieExpire($expire) + { + self::$langCookieExpire = $expire; + } + /** * 设置允许的语言列表 * @param array $list 语言列表 diff --git a/core/library/think/Loader.php b/core/library/think/Loader.php index ef86720c..cfa0a217 100644 --- a/core/library/think/Loader.php +++ b/core/library/think/Loader.php @@ -322,7 +322,7 @@ class Loader //加载当前模块应用类库 $baseUrl = App::$modulePath; } elseif (is_dir(EXTEND_PATH . $name)) { - $baseUrl = EXTEND_PATH; + $baseUrl = EXTEND_PATH . $name . DS; } else { // 加载其它模块的类库 $baseUrl = APP_PATH . $name . DS; diff --git a/core/library/think/Model.php b/core/library/think/Model.php index 6ac90cc8..f062e3c5 100644 --- a/core/library/think/Model.php +++ b/core/library/think/Model.php @@ -13,6 +13,7 @@ namespace think; use InvalidArgumentException; use think\Cache; +use think\Config; use think\Db; use think\db\Query; use think\Exception; @@ -99,7 +100,7 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // 验证失败是否抛出异常 protected $failException = false; // 全局查询范围 - protected static $useGlobalScope = true; + protected $useGlobalScope = true; /** * 初始化过的模型. @@ -126,7 +127,12 @@ abstract class Model implements \JsonSerializable, \ArrayAccess 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)) { @@ -141,9 +147,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess /** * 获取当前模型的数据库查询对象 * @access public + * @param bool $baseQuery 是否调用全局查询范围 * @return Query */ - public function db() + public function db($baseQuery = true) { $model = $this->class; if (!isset(self::$links[$model])) { @@ -163,6 +170,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess self::$links[$model] = $query; } + // 全局作用域 + if ($baseQuery && method_exists($this, 'base')) { + call_user_func_array([$this, 'base'], [ & self::$links[$model]]); + } // 返回当前模型的数据库查询对象 return self::$links[$model]; } @@ -401,9 +412,10 @@ abstract class Model implements \JsonSerializable, \ArrayAccess // 类型转换 $value = $this->readTransform($value, $this->type[$name]); } 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; } else { @@ -1109,8 +1121,8 @@ abstract class Model implements \JsonSerializable, \ArrayAccess */ public static function useGlobalScope($use) { - $model = new static(); - static::$useGlobalScope = $use; + $model = new static(); + $model->useGlobalScope = $use; return $model; } @@ -1333,10 +1345,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess public function __call($method, $args) { $query = $this->db(); - // 全局作用域 - if (static::$useGlobalScope && method_exists($this, 'base')) { - call_user_func_array('static::base', [ & $query]); - } if (method_exists($this, 'scope' . $method)) { // 动态调用命名范围 $method = 'scope' . $method; @@ -1351,11 +1359,6 @@ abstract class Model implements \JsonSerializable, \ArrayAccess public static function __callStatic($method, $params) { $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); } diff --git a/core/library/think/Request.php b/core/library/think/Request.php index 1a8b6046..077e190d 100644 --- a/core/library/think/Request.php +++ b/core/library/think/Request.php @@ -1476,23 +1476,37 @@ class Request */ public function cache($key, $expire = null) { - if (false !== strpos($key, ':')) { - $param = $this->param(); - foreach ($param as $item => $val) { - if (is_string($val) && false !== strpos($key, ':' . $item)) { - $key = str_replace(':' . $item, $val, $key); + if ($this->isGet()) { + if (false !== strpos($key, ':')) { + $param = $this->param(); + foreach ($param as $item => $val) { + if (is_string($val) && false !== strpos($key, ':' . $item)) { + $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)) { - // 读取缓存 - $content = Cache::get($key); - $response = Response::create($content) - ->code(304) - ->header('Content-Type', Cache::get($key . '_header')); - throw new \think\exception\HttpResponseException($response); - } else { - $this->cache = [$key, $expire]; + + if (strtotime($this->server('HTTP_IF_MODIFIED_SINCE')) + $expire > $_SERVER['REQUEST_TIME']) { + // 读取缓存 + $response = Response::create()->code(304); + throw new \think\exception\HttpResponseException($response); + } elseif (Cache::has($key)) { + list($content, $header) = Cache::get($key); + $response = Response::create($content)->header($header); + throw new \think\exception\HttpResponseException($response); + } else { + $this->cache = [$key, $expire]; + } } } diff --git a/core/library/think/Response.php b/core/library/think/Response.php index d5ab5827..8b62e419 100644 --- a/core/library/think/Response.php +++ b/core/library/think/Response.php @@ -111,15 +111,17 @@ class Response header($name . ':' . $val); } } - echo $data; - if (200 == $this->code) { $cache = Request::instance()->getCache(); if ($cache) { - Cache::set($cache[0], $data, $cache[1]); - Cache::set($cache[0] . '_header', $this->header['Content-Type']); + header('Cache-Control: max-age=' . $cache[1] . ',must-revalidate'); + 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')) { // 提高页面响应 diff --git a/core/library/think/Route.php b/core/library/think/Route.php index 339e4903..c7c4a731 100644 --- a/core/library/think/Route.php +++ b/core/library/think/Route.php @@ -830,7 +830,7 @@ class Route if (true === $rule) { $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']); } } diff --git a/core/library/think/Template.php b/core/library/think/Template.php index c82850c3..036b367e 100644 --- a/core/library/think/Template.php +++ b/core/library/think/Template.php @@ -977,14 +977,14 @@ class Template break; case 'COOKIE': if (isset($vars[2])) { - $parseStr = '$_COOKIE[\'' . $vars[1] . '\'][\'' . $vars[2] . '\']'; + $parseStr = '\\think\\Cookie::get(\'' . $vars[1] . '.' . $vars[2] . '\')'; } else { $parseStr = '\\think\\Cookie::get(\'' . $vars[1] . '\')'; } break; case 'SESSION': if (isset($vars[2])) { - $parseStr = '$_SESSION[\'' . $vars[1] . '\'][\'' . $vars[2] . '\']'; + $parseStr = '\\think\\Session::get(\'' . $vars[1] . '.' . $vars[2] . '\')'; } else { $parseStr = '\\think\\Session::get(\'' . $vars[1] . '\')'; } diff --git a/core/library/think/cache/Driver.php b/core/library/think/cache/Driver.php index f77ac30b..e0aeb7bc 100644 --- a/core/library/think/cache/Driver.php +++ b/core/library/think/cache/Driver.php @@ -16,6 +16,7 @@ namespace think\cache; */ abstract class Driver { + protected $handler = null; protected $options = []; protected $tag; @@ -173,4 +174,15 @@ abstract class Driver return []; } } + + /** + * 返回句柄对象,可执行其它高级方法 + * + * @access public + * @return object + */ + public function handler() + { + return $this->handler; + } } diff --git a/core/library/think/cache/driver/File.php b/core/library/think/cache/driver/File.php index ea5688e5..5c98d799 100644 --- a/core/library/think/cache/driver/File.php +++ b/core/library/think/cache/driver/File.php @@ -221,9 +221,13 @@ class File extends Driver $this->rm('tag_' . md5($tag)); return true; } - $fileLsit = (array) glob($this->options['path'] . '*'); - foreach ($fileLsit as $path) { - is_file($path) && unlink($path); + $files = (array) glob($this->options['path'] . ($this->options['prefix'] ? $this->options['prefix'] . DS : '') . '*'); + foreach ($files as $path) { + if (is_dir($path)) { + array_map('unlink', glob($path . '/*.php')); + } else { + unlink($path); + } } return true; } diff --git a/core/library/think/cache/driver/Lite.php b/core/library/think/cache/driver/Lite.php index 9e702eed..b9d10097 100644 --- a/core/library/think/cache/driver/Lite.php +++ b/core/library/think/cache/driver/Lite.php @@ -180,6 +180,6 @@ class Lite extends Driver $this->rm('tag_' . md5($tag)); 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')); } } diff --git a/core/library/think/cache/driver/Memcache.php b/core/library/think/cache/driver/Memcache.php index 8e3df294..bddf7157 100644 --- a/core/library/think/cache/driver/Memcache.php +++ b/core/library/think/cache/driver/Memcache.php @@ -16,7 +16,6 @@ use think\Exception; class Memcache extends Driver { - protected $handler = null; protected $options = [ 'host' => '127.0.0.1', 'port' => 11211, diff --git a/core/library/think/cache/driver/Memcached.php b/core/library/think/cache/driver/Memcached.php index 5857edce..4c4505b0 100644 --- a/core/library/think/cache/driver/Memcached.php +++ b/core/library/think/cache/driver/Memcached.php @@ -15,7 +15,6 @@ use think\cache\Driver; class Memcached extends Driver { - protected $handler; protected $options = [ 'host' => '127.0.0.1', 'port' => 11211, diff --git a/core/library/think/cache/driver/Redis.php b/core/library/think/cache/driver/Redis.php index 1f8686af..e7f78762 100644 --- a/core/library/think/cache/driver/Redis.php +++ b/core/library/think/cache/driver/Redis.php @@ -22,7 +22,6 @@ use think\cache\Driver; */ class Redis extends Driver { - protected $handler = null; protected $options = [ 'host' => '127.0.0.1', 'port' => 6379, @@ -174,14 +173,4 @@ class Redis extends Driver return $this->handler->flushDB(); } - /** - * 返回句柄对象,可执行其它高级方法 - * - * @access public - * @return object - */ - public function handler() - { - return $this->handler; - } } diff --git a/core/library/think/cache/driver/Sqlite.php b/core/library/think/cache/driver/Sqlite.php index 0b774a1a..6dbd41fe 100644 --- a/core/library/think/cache/driver/Sqlite.php +++ b/core/library/think/cache/driver/Sqlite.php @@ -20,7 +20,6 @@ use think\Exception; */ class Sqlite extends Driver { - protected $options = [ 'db' => ':memory:', 'table' => 'sharedmemory', diff --git a/core/library/think/cache/driver/Wincache.php b/core/library/think/cache/driver/Wincache.php index 36fe3bea..a9cc7d22 100644 --- a/core/library/think/cache/driver/Wincache.php +++ b/core/library/think/cache/driver/Wincache.php @@ -25,8 +25,6 @@ class Wincache extends Driver 'expire' => 0, ]; - protected $tag; - /** * 架构函数 * @param array $options 缓存参数 diff --git a/core/library/think/db/Query.php b/core/library/think/db/Query.php index b498b1ea..2e9308cc 100644 --- a/core/library/think/db/Query.php +++ b/core/library/think/db/Query.php @@ -489,51 +489,51 @@ class Query */ public function count($field = '*') { - return $this->value('COUNT(' . $field . ') AS tp_count', 0); + return (int) $this->value('COUNT(' . $field . ') AS tp_count', 0); } /** * SUM查询 * @access public * @param string $field 字段名 - * @return integer + * @return float|int */ public function sum($field = '*') { - return $this->value('SUM(' . $field . ') AS tp_sum', 0); + return $this->value('SUM(' . $field . ') AS tp_sum', 0) + 0; } /** * MIN查询 * @access public * @param string $field 字段名 - * @return integer + * @return float|int */ public function min($field = '*') { - return $this->value('MIN(' . $field . ') AS tp_min', 0); + return $this->value('MIN(' . $field . ') AS tp_min', 0) + 0; } /** * MAX查询 * @access public * @param string $field 字段名 - * @return integer + * @return float|int */ public function max($field = '*') { - return $this->value('MAX(' . $field . ') AS tp_max', 0); + return $this->value('MAX(' . $field . ') AS tp_max', 0) + 0; } /** * AVG查询 * @access public * @param string $field 字段名 - * @return integer + * @return float|int */ 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 bool $simple 简洁模式 + * @param int|bool $simple 简洁模式或者总记录数 * @param array $config 配置参数 * page:当前页, * path:url路径, @@ -986,6 +986,10 @@ class Query */ public function paginate($listRows = null, $simple = false, $config = []) { + if (is_int($simple)) { + $total = $simple; + $simple = false; + } $config = array_merge(Config::get('paginate'), $config); $listRows = $listRows ?: $config['list_rows']; @@ -1000,16 +1004,17 @@ class Query $config['path'] = isset($config['path']) ? $config['path'] : call_user_func([$class, 'getCurrentPath']); - if (!$simple) { + if (!isset($total) && !$simple) { $options = $this->getOptions(); $total = $this->count(); $bind = $this->bind; $results = $this->options($options)->bind($bind)->page($page, $listRows)->select(); - } else { + } elseif ($simple) { $results = $this->limit(($page - 1) * $listRows, $listRows + 1)->select(); $total = null; + } else { + $results = $this->page($page, $listRows)->select(); } - return $class::make($results, $listRows, $page, $total, $simple, $config); } @@ -1482,7 +1487,11 @@ class Query */ 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; + } } /** diff --git a/core/library/think/db/builder/Mysql.php b/core/library/think/db/builder/Mysql.php index 84853307..04586906 100644 --- a/core/library/think/db/builder/Mysql.php +++ b/core/library/think/db/builder/Mysql.php @@ -32,7 +32,7 @@ class Mysql extends Builder if (strpos($key, '$.') && false === strpos($key, '(')) { // JSON字段支持 list($field, $name) = explode('$.', $key); - $key = 'jsn_extract(' . $field . ', \'$.\'.' . $name . ')'; + $key = 'json_extract(' . $field . ', \'$.' . $name . '\')'; } if (!preg_match('/[,\'\"\*\(\)`.\s]/', $key)) { $key = '`' . $key . '`'; diff --git a/core/library/think/exception/Handle.php b/core/library/think/exception/Handle.php index ad05c70b..8b6e6c40 100644 --- a/core/library/think/exception/Handle.php +++ b/core/library/think/exception/Handle.php @@ -203,10 +203,6 @@ class Handle if (IS_CLI) { return $message; } - // 导入语言包 - if (!Config::get('lang_switch_on')) { - Lang::load(THINK_PATH . 'lang' . DS . Lang::detect() . EXT); - } if (strpos($message, ':')) { $name = strstr($message, ':', true); diff --git a/core/library/think/model/Merge.php b/core/library/think/model/Merge.php index e03fd90c..c28d0fd7 100644 --- a/core/library/think/model/Merge.php +++ b/core/library/think/model/Merge.php @@ -17,9 +17,9 @@ use think\Model; class Merge extends Model { - protected static $relationModel = []; // HAS ONE 关联的模型列表 - protected $fk = ''; // 外键名 默认为主表名_id - protected $mapFields = []; // 需要处理的模型映射字段,避免混淆 array( id => 'user.id' ) + protected $relationModel = []; // HAS ONE 关联的模型列表 + protected $fk = ''; // 外键名 默认为主表名_id + protected $mapFields = []; // 需要处理的模型映射字段,避免混淆 array( id => 'user.id' ) /** * 架构函数 @@ -64,7 +64,7 @@ class Merge extends Model $fields = self::getModelField($query, $master, '', $class->mapFields); $query->alias($master)->field($fields); - foreach (static::$relationModel as $key => $model) { + foreach ($class->relationModel as $key => $model) { $name = is_int($key) ? $model : $key; $table = is_int($key) ? $query->getTable($name) : $model; $query->join($table . ' ' . $name, $name . '.' . $class->fk . '=' . $master . '.' . $class->getPk()); @@ -126,7 +126,7 @@ class Merge extends Model $item = []; foreach ($data as $key => $val) { 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]); if ($model == $name) { $item[$key] = $val; @@ -203,7 +203,7 @@ class Merge extends Model $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; $table = is_int($key) ? $db->getTable($model) : $model; // 处理关联模型数据 @@ -213,6 +213,8 @@ class Merge extends Model $result = 1; } } + // 清空change + $this->change = []; // 新增回调 $this->trigger('after_update', $this); } else { @@ -239,16 +241,19 @@ class Merge extends Model if ($insertId) { if (is_string($pk)) { $this->data[$pk] = $insertId; + if ($this->fk == $pk) { + $this->change[] = $pk; + } } $this->data[$this->fk] = $insertId; } // 写入附表数据 $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]); } - foreach (static::$relationModel as $key => $model) { + foreach ($this->relationModel as $key => $model) { $name = is_int($key) ? $model : $key; $table = is_int($key) ? $db->getTable($model) : $model; // 处理关联模型数据 @@ -257,6 +262,10 @@ class Merge extends Model $query->table($table)->strict(false)->insert($data); } } + // 标记为更新 + $this->isUpdate = true; + // 清空change + $this->change = []; // 新增回调 $this->trigger('after_insert', $this); } @@ -288,7 +297,7 @@ class Merge extends Model $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; $query = clone $db; $query->table($table)->where($this->fk, $pk)->delete(); diff --git a/core/library/think/model/Relation.php b/core/library/think/model/Relation.php index 69b80270..22670bdd 100644 --- a/core/library/think/model/Relation.php +++ b/core/library/think/model/Relation.php @@ -318,11 +318,7 @@ class Relation } } - if (!isset($list[$relation])) { - // 设置关联模型属性 - $list[$relation] = []; - } - $result->setAttr($relation, (new $model($list[$relation]))->isUpdate(true)); + $result->setAttr($relation, !isset($list[$relation]) ? null : (new $model($list[$relation]))->isUpdate(true)); } /** diff --git a/core/library/traits/model/SoftDelete.php b/core/library/traits/model/SoftDelete.php index cbfa275f..e08d96aa 100644 --- a/core/library/traits/model/SoftDelete.php +++ b/core/library/traits/model/SoftDelete.php @@ -12,7 +12,8 @@ trait SoftDelete */ public function trashed() { - if (!empty($this->data[static::$deleteTime])) { + $field = $this->getDeleteTimeField(); + if (!empty($this->data[$field])) { return true; } return false; @@ -37,7 +38,8 @@ trait SoftDelete public static function onlyTrashed() { $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)) { return false; } - - if (static::$deleteTime && !$force) { + $name = $this->getDeleteTimeField(); + if (!$force) { // 软删除 - $name = static::$deleteTime; $this->change[] = $name; $this->data[$name] = $this->autoWriteTimestamp($name); $result = $this->isUpdate()->save(); @@ -106,12 +107,10 @@ trait SoftDelete */ public function restore($where = []) { - if (static::$deleteTime) { - // 恢复删除 - $name = static::$deleteTime; - return $this->isUpdate()->save([$name => null], $where); - } - return false; + $name = $this->getDeleteTimeField(); + // 恢复删除 + return $this->isUpdate()->save([$name => null], $where); + } /** @@ -120,11 +119,28 @@ trait SoftDelete * @param \think\db\Query $query 查询对象 * @return void */ - protected static function base($query) + protected function base($query) { - if (static::$deleteTime) { - $query->where(static::$deleteTime, 'null'); - } + $field = $this->getDeleteTimeField(true); + $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; + } }