diff --git a/core/library/think/App.php b/core/library/think/App.php index c52c0ff7..c0fed042 100644 --- a/core/library/think/App.php +++ b/core/library/think/App.php @@ -424,11 +424,6 @@ class App // 加载模块配置 $config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT); - // 加载应用状态配置 - if ($config['app_status']) { - $config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT); - } - // 读取扩展配置文件 if ($config['extra_config_list']) { foreach ($config['extra_config_list'] as $name => $file) { @@ -437,6 +432,11 @@ class App } } + // 加载应用状态配置 + if ($config['app_status']) { + $config = Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT); + } + // 加载别名文件 if (is_file(CONF_PATH . $module . 'alias' . EXT)) { Loader::addClassMap(include CONF_PATH . $module . 'alias' . EXT); diff --git a/core/library/think/Cache.php b/core/library/think/Cache.php index 3bbd3e3a..9f7a569d 100644 --- a/core/library/think/Cache.php +++ b/core/library/think/Cache.php @@ -31,7 +31,7 @@ class Cache * @access public * @param array $options 配置数组 * @param bool|string $name 缓存连接标识 true 强制重新连接 - * @return object + * @return \think\cache\Driver */ public static function connect(array $options = [], $name = false) { @@ -65,10 +65,30 @@ class Cache { if (is_null(self::$handler)) { // 自动初始化缓存 - self::connect($options ?: Config::get('cache')); + if (!empty($options)) { + self::connect($options); + } elseif ('complex' == Config::get('cache.type')) { + self::connect(Config::get('cache.default')); + } else { + self::connect(Config::get('cache')); + } } } + /** + * 切换缓存类型 需要配置 cache.type 为 complex + * @access public + * @param string $name 缓存标识 + * @return \think\cache\Driver + */ + public static function store($name) + { + if ('complex' == Config::get('cache.type')) { + self::connect(Config::get('cache.' . $name), strtolower($name)); + } + return self::$handler; + } + /** * 判断缓存是否存在 * @access public @@ -155,13 +175,28 @@ class Cache /** * 清除缓存 * @access public + * @param string $tag 标签名 * @return boolean */ - public static function clear() + public static function clear($tag = null) { self::init(); self::$writeTimes++; - return self::$handler->clear(); + return self::$handler->clear($tag); + } + + /** + * 缓存标签 + * @access public + * @param string $name 标签名 + * @param string|array $keys 缓存标识 + * @param bool $overlay 是否覆盖 + * @return \think\cache\Driver + */ + public static function tag($name, $keys = null, $overlay = false) + { + self::init(); + return self::$handler->tag($name, $keys, $overlay); } } diff --git a/core/library/think/Db.php b/core/library/think/Db.php index 8b187e0f..9aefbe38 100644 --- a/core/library/think/Db.php +++ b/core/library/think/Db.php @@ -33,6 +33,7 @@ use think\paginator\Collection as PaginatorCollection; * @method mixed find(mixed $data = []) static 查询单个记录 * @method mixed select(mixed $data = []) static 查询多个记录 * @method integer insert(array $data, boolean $replace = false, boolean $getLastInsID = false, string $sequence = null) static 插入一条记录 + * @method integer insertGetId(array $data, boolean $replace = false, string $sequence = null) static 插入一条记录并返回自增ID * @method integer insertAll(array $dataSet) static 插入多条记录 * @method integer update(array $data) static 更新记录 * @method integer delete(mixed $data = []) static 删除记录 diff --git a/core/library/think/Request.php b/core/library/think/Request.php index 4449b97f..4d98c1e7 100644 --- a/core/library/think/Request.php +++ b/core/library/think/Request.php @@ -128,7 +128,9 @@ class Request $this->$name = $item; } } - $this->filter = Config::get('default_filter'); + if (is_null($this->filter)) { + $this->filter = Config::get('default_filter'); + } } public function __call($method, $args) @@ -653,11 +655,12 @@ class Request */ public function get($name = '', $default = null, $filter = null) { + if (empty($this->get)) { + $this->get = $_GET; + } if (is_array($name)) { $this->param = []; return $this->get = array_merge($this->get, $name); - } elseif (empty($this->get)) { - $this->get = $_GET; } return $this->input($this->get, $name, $default, $filter); } @@ -672,11 +675,12 @@ class Request */ public function post($name = '', $default = null, $filter = null) { + if (empty($this->post)) { + $this->post = $_POST; + } if (is_array($name)) { $this->param = []; return $this->post = array_merge($this->post, $name); - } elseif (empty($this->post)) { - $this->post = $_POST; } return $this->input($this->post, $name, $default, $filter); } @@ -691,10 +695,6 @@ class Request */ public function put($name = '', $default = null, $filter = null) { - if (is_array($name)) { - $this->param = []; - return $this->put = is_null($this->put) ? $name : array_merge($this->put, $name); - } if (is_null($this->put)) { $content = file_get_contents('php://input'); if (strpos($content, '":')) { @@ -703,6 +703,11 @@ class Request parse_str($content, $this->put); } } + if (is_array($name)) { + $this->param = []; + return $this->put = is_null($this->put) ? $name : array_merge($this->put, $name); + } + return $this->input($this->put, $name, $default, $filter); } @@ -741,11 +746,12 @@ class Request */ public function request($name = '', $default = null, $filter = null) { + if (empty($this->request)) { + $this->request = $_REQUEST; + } if (is_array($name)) { $this->param = []; return $this->request = array_merge($this->request, $name); - } elseif (empty($this->request)) { - $this->request = $_REQUEST; } return $this->input($this->request ?: $_REQUEST, $name, $default, $filter); } @@ -760,10 +766,11 @@ class Request */ public function session($name = '', $default = null, $filter = null) { + if (empty($this->session)) { + $this->session = Session::get(); + } if (is_array($name)) { return $this->session = array_merge($this->session, $name); - } elseif (empty($this->session)) { - $this->session = Session::get(); } return $this->input($this->session, $name, $default, $filter); } @@ -778,10 +785,11 @@ class Request */ public function cookie($name = '', $default = null, $filter = null) { + if (empty($this->cookie)) { + $this->cookie = $_COOKIE; + } if (is_array($name)) { return $this->cookie = array_merge($this->cookie, $name); - } elseif (empty($this->cookie)) { - $this->cookie = $_COOKIE; } return $this->input($this->cookie, $name, $default, $filter); } @@ -796,10 +804,11 @@ class Request */ public function server($name = '', $default = null, $filter = null) { + if (empty($this->server)) { + $this->server = $_SERVER; + } if (is_array($name)) { return $this->server = array_merge($this->server, $name); - } elseif (empty($this->server)) { - $this->server = $_SERVER; } return $this->input($this->server, false === $name ? false : strtoupper($name), $default, $filter); } @@ -812,10 +821,11 @@ class Request */ public function file($name = '') { + if (empty($this->file)) { + $this->file = isset($_FILES) ? $_FILES : []; + } if (is_array($name)) { return $this->file = array_merge($this->file, $name); - } elseif (empty($this->file)) { - $this->file = isset($_FILES) ? $_FILES : []; } $files = $this->file; if (!empty($files)) { @@ -872,10 +882,11 @@ class Request */ public function env($name = '', $default = null, $filter = null) { + if (empty($this->env)) { + $this->env = $_ENV; + } if (is_array($name)) { return $this->env = array_merge($this->env, $name); - } elseif (empty($this->env)) { - $this->env = $_ENV; } return $this->input($this->env, false === $name ? false : strtoupper($name), $default, $filter); } @@ -889,9 +900,7 @@ class Request */ public function header($name = '', $default = null) { - if (is_array($name)) { - return $this->header = array_merge($this->header, $name); - } elseif (empty($this->header)) { + if (empty($this->header)) { $header = []; $server = $this->server ?: $_SERVER; foreach ($server as $key => $val) { @@ -908,6 +917,9 @@ class Request } $this->header = array_change_key_case($header); } + if (is_array($name)) { + return $this->header = array_merge($this->header, $name); + } if ('' === $name) { return $this->header; } @@ -1169,7 +1181,8 @@ class Request */ public function isAjax() { - return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false; + $value = $this->server('HTTP_X_REQUESTED_WITH'); + return (!is_null($value) && strtolower($value) == 'xmlhttprequest') ? true : false; } /** @@ -1179,7 +1192,7 @@ class Request */ public function isPjax() { - return (isset($_SERVER['HTTP_X_PJAX']) && $_SERVER['HTTP_X_PJAX']) ? true : false; + return !is_null($this->server('HTTP_X_PJAX')) ? true : false; } /** diff --git a/core/library/think/Route.php b/core/library/think/Route.php index 95904ee0..44ef6d40 100644 --- a/core/library/think/Route.php +++ b/core/library/think/Route.php @@ -233,7 +233,7 @@ class Route public static function rule($rule, $route = '', $type = '*', $option = [], $pattern = []) { $group = self::getGroup('name'); - if (!empty($group)) { + if (!is_null($group)) { // 路由分组 $option = array_merge(self::getGroup('option'), $option); $pattern = array_merge(self::getGroup('pattern'), $pattern); @@ -281,6 +281,8 @@ class Route if (is_array($rule)) { $name = $rule[0]; $rule = $rule[1]; + } elseif (is_string($route)) { + $name = $route; } if ('$' == substr($rule, -1, 1)) { // 是否完整匹配 diff --git a/core/library/think/Url.php b/core/library/think/Url.php index 2d2acb82..a2d5e3d0 100644 --- a/core/library/think/Url.php +++ b/core/library/think/Url.php @@ -73,15 +73,16 @@ class Url parse_str($info['query'], $params); $vars = array_merge($params, $vars); } - - $rule = Route::name(isset($name) ? $name : $url); - if ($rule && $match = self::getRuleUrl($rule, $vars)) { + if ($url) { + $rule = Route::name(isset($name) ? $name : $url); + } + if (!empty($rule) && $match = self::getRuleUrl($rule, $vars)) { // 匹配路由命名标识 快速生成 $url = $match; if (!empty($rule[2])) { $domain = $rule[2]; } - } elseif ($rule && isset($name)) { + } elseif (!empty($rule) && isset($name)) { throw new \InvalidArgumentException('route name not exists:' . $name); } else { // 获取路由别名 diff --git a/core/library/think/cache/Driver.php b/core/library/think/cache/Driver.php new file mode 100644 index 00000000..021ae727 --- /dev/null +++ b/core/library/think/cache/Driver.php @@ -0,0 +1,159 @@ + +// +---------------------------------------------------------------------- + +namespace think\cache; + +/** + * 缓存基础类 + */ +abstract class Driver +{ + protected $options = []; + protected $tag; + + /** + * 判断缓存是否存在 + * @access public + * @param string $name 缓存变量名 + * @return bool + */ + abstract public function has($name); + + /** + * 读取缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $default 默认值 + * @return mixed + */ + abstract public function get($name, $default = false); + + /** + * 写入缓存 + * @access public + * @param string $name 缓存变量名 + * @param mixed $value 存储数据 + * @param int $expire 有效时间 0为永久 + * @return boolean + */ + abstract public function set($name, $value, $expire = null); + + /** + * 自增缓存(针对数值缓存) + * @access public + * @param string $name 缓存变量名 + * @param int $step 步长 + * @return false|int + */ + abstract public function inc($name, $step = 1); + + /** + * 自减缓存(针对数值缓存) + * @access public + * @param string $name 缓存变量名 + * @param int $step 步长 + * @return false|int + */ + abstract public function dec($name, $step = 1); + + /** + * 删除缓存 + * @access public + * @param string $name 缓存变量名 + * @return boolean + */ + abstract public function rm($name); + + /** + * 清除缓存 + * @access public + * @param string $tag 标签名 + * @return boolean + */ + abstract public function clear($tag = null); + + /** + * 获取实际的缓存标识 + * @access public + * @param string $name 缓存名 + * @return string + */ + protected function getCacheKey($name) + { + return $this->options['prefix'] . $name; + } + + /** + * 缓存标签 + * @access public + * @param string $name 标签名 + * @param string|array $keys 缓存标识 + * @param bool $overlay 是否覆盖 + * @return $this + */ + public function tag($name, $keys = null, $overlay = false) + { + if (is_null($keys)) { + $this->tag = $name; + } else { + $key = 'tag_' . md5($name); + if (is_string($keys)) { + $keys = explode(',', $keys); + } + $keys = array_map([$this, 'getCacheKey'], $keys); + if ($overlay) { + $value = $keys; + } else { + $value = array_unique(array_merge($this->getTagItem($name), $keys)); + } + $this->set($key, implode(',', $value)); + } + return $this; + } + + /** + * 更新标签 + * @access public + * @param string $name 缓存标识 + * @return void + */ + protected function setTagItem($name) + { + if ($this->tag) { + $key = 'tag_' . md5($this->tag); + $this->tag = null; + if ($this->has($key)) { + $value = $this->get($key); + $value .= ',' . $name; + } else { + $value = $name; + } + $this->set($key, $value); + } + } + + /** + * 获取标签包含的缓存标识 + * @access public + * @param string $tag 缓存标签 + * @return array + */ + protected function getTagItem($tag) + { + $key = 'tag_' . md5($tag); + $value = $this->get($key); + if ($value) { + return explode(',', $value); + } else { + return []; + } + } +} diff --git a/core/library/think/cache/driver/File.php b/core/library/think/cache/driver/File.php index 1f4b91f8..da3b3f6f 100644 --- a/core/library/think/cache/driver/File.php +++ b/core/library/think/cache/driver/File.php @@ -11,11 +11,13 @@ namespace think\cache\driver; +use think\cache\Driver; + /** * 文件类型缓存类 * @author liu21st */ -class File +class File extends Driver { protected $options = [ 'expire' => 0, @@ -58,16 +60,16 @@ class File /** * 取得变量的存储文件名 - * @access private + * @access protected * @param string $name 缓存变量名 * @return string */ - private function filename($name) + protected function getCacheKey($name) { $name = md5($name); if ($this->options['cache_subdir']) { // 使用子目录 - $name = substr($md5, 0, 2) . DS . substr($md5, 2); + $name = substr($name, 0, 2) . DS . substr($name, 2); } if ($this->options['prefix']) { $name = $this->options['prefix'] . DS . $name; @@ -88,7 +90,7 @@ class File */ public function has($name) { - $filename = $this->filename($name); + $filename = $this->getCacheKey($name); return is_file($filename); } @@ -101,7 +103,7 @@ class File */ public function get($name, $default = false) { - $filename = $this->filename($name); + $filename = $this->getCacheKey($name); if (!is_file($filename)) { return $default; } @@ -138,8 +140,11 @@ class File if (is_null($expire)) { $expire = $this->options['expire']; } - $filename = $this->filename($name); - $data = serialize($value); + $filename = $this->getCacheKey($name); + if ($this->tag && !is_file($filename)) { + $first = true; + } + $data = serialize($value); if ($this->options['data_compress'] && function_exists('gzcompress')) { //数据压缩 $data = gzcompress($data, 3); @@ -147,6 +152,7 @@ class File $data = ""; $result = file_put_contents($filename, $data); if ($result) { + isset($first) && $this->setTagItem($filename); clearstatcache(); return true; } else { @@ -196,16 +202,26 @@ class File */ public function rm($name) { - return $this->unlink($this->filename($name)); + return $this->unlink($this->getCacheKey($name)); } /** * 清除缓存 * @access public + * @param string $tag 标签名 * @return boolean */ - public function clear() + public function clear($tag = null) { + if ($tag) { + // 指定标签清除 + $keys = $this->getTagItem($tag); + foreach ($keys as $key) { + $this->unlink($key); + } + $this->rm('tag_' . md5($tag)); + return true; + } $fileLsit = (array) glob($this->options['path'] . '*'); foreach ($fileLsit as $path) { is_file($path) && unlink($path); @@ -224,4 +240,5 @@ class File { return is_file($path) && unlink($path); } + } diff --git a/core/library/think/cache/driver/Lite.php b/core/library/think/cache/driver/Lite.php index 41c94d06..a527a012 100644 --- a/core/library/think/cache/driver/Lite.php +++ b/core/library/think/cache/driver/Lite.php @@ -11,11 +11,13 @@ namespace think\cache\driver; +use think\cache\Driver; + /** * 文件类型缓存类 * @author liu21st */ -class Lite +class Lite extends Driver { protected $options = [ 'prefix' => '', @@ -42,11 +44,11 @@ class Lite /** * 取得变量的存储文件名 - * @access private + * @access protected * @param string $name 缓存变量名 * @return string */ - private function filename($name) + protected function getCacheKey($name) { return $this->options['path'] . $this->options['prefix'] . md5($name) . '.php'; } @@ -59,7 +61,7 @@ class Lite */ public function has($name) { - $filename = $this->filename($name); + $filename = $this->getCacheKey($name); return is_file($filename); } @@ -72,7 +74,7 @@ class Lite */ public function get($name, $default = false) { - $filename = $this->filename($name); + $filename = $this->getCacheKey($name); if (is_file($filename)) { // 判断是否过期 $mtime = filemtime($filename); @@ -104,10 +106,14 @@ class Lite if (0 === $expire) { $expire = 10 * 365 * 24 * 3600; } - $filename = $this->filename($name); - $ret = file_put_contents($filename, ("getCacheKey($name); + if ($this->tag && !is_file($filename)) { + $first = true; + } + $ret = file_put_contents($filename, ("setTagItem($filename); touch($filename, $_SERVER['REQUEST_TIME'] + $expire); } return $ret; @@ -155,18 +161,26 @@ class Lite */ public function rm($name) { - return unlink($this->filename($name)); + return unlink($this->getCacheKey($name)); } /** * 清除缓存 * @access public + * @param string $tag 标签名 * @return bool - * @internal param string $name 缓存变量名 */ - public function clear() + public function clear($tag = null) { - $filename = $this->filename('*'); - array_map("unlink", glob($filename)); + if ($tag) { + // 指定标签清除 + $keys = $this->getTagItem($tag); + foreach ($keys as $key) { + unlink($key); + } + $this->rm('tag_' . md5($tag)); + return true; + } + array_map("unlink", glob($this->options['path'] . $this->options['prefix'] . '*.php')); } } diff --git a/core/library/think/cache/driver/Memcache.php b/core/library/think/cache/driver/Memcache.php index aacba930..8e3df294 100644 --- a/core/library/think/cache/driver/Memcache.php +++ b/core/library/think/cache/driver/Memcache.php @@ -11,9 +11,10 @@ namespace think\cache\driver; +use think\cache\Driver; use think\Exception; -class Memcache +class Memcache extends Driver { protected $handler = null; protected $options = [ @@ -63,8 +64,8 @@ class Memcache */ public function has($name) { - $name = $this->options['prefix'] . $name; - return $this->handler->get($name) ? true : false; + $key = $this->getCacheKey($name); + return $this->handler->get($key) ? true : false; } /** @@ -76,7 +77,7 @@ class Memcache */ public function get($name, $default = false) { - $result = $this->handler->get($this->options['prefix'] . $name); + $result = $this->handler->get($this->getCacheKey($name)); return false !== $result ? $result : $default; } @@ -93,8 +94,12 @@ class Memcache if (is_null($expire)) { $expire = $this->options['expire']; } - $name = $this->options['prefix'] . $name; - if ($this->handler->set($name, $value, 0, $expire)) { + if ($this->tag && !$this->has($name)) { + $first = true; + } + $key = $this->getCacheKey($name); + if ($this->handler->set($key, $value, 0, $expire)) { + isset($first) && $this->setTagItem($key); return true; } return false; @@ -109,8 +114,8 @@ class Memcache */ public function inc($name, $step = 1) { - $name = $this->options['prefix'] . $name; - return $this->handler->increment($name, $step); + $key = $this->getCacheKey($name); + return $this->handler->increment($key, $step); } /** @@ -122,9 +127,9 @@ class Memcache */ public function dec($name, $step = 1) { - $name = $this->options['prefix'] . $name; - $value = $this->handler->get($name) - $step; - $res = $this->handler->set($name, $value); + $key = $this->getCacheKey($name); + $value = $this->handler->get($key) - $step; + $res = $this->handler->set($key, $value); if (!$res) { return false; } else { @@ -140,19 +145,29 @@ class Memcache */ public function rm($name, $ttl = false) { - $name = $this->options['prefix'] . $name; + $key = $this->getCacheKey($name); return false === $ttl ? - $this->handler->delete($name) : - $this->handler->delete($name, $ttl); + $this->handler->delete($key) : + $this->handler->delete($key, $ttl); } /** * 清除缓存 * @access public + * @param string $tag 标签名 * @return bool */ - public function clear() + public function clear($tag = null) { + if ($tag) { + // 指定标签清除 + $keys = $this->getTagItem($tag); + foreach ($keys as $key) { + $this->handler->delete($key); + } + $this->rm('tag_' . md5($tag)); + return true; + } return $this->handler->flush(); } } diff --git a/core/library/think/cache/driver/Memcached.php b/core/library/think/cache/driver/Memcached.php index f260fec6..9c0a2597 100644 --- a/core/library/think/cache/driver/Memcached.php +++ b/core/library/think/cache/driver/Memcached.php @@ -11,7 +11,9 @@ namespace think\cache\driver; -class Memcached +use think\cache\Driver; + +class Memcached extends Driver { protected $handler; protected $options = [ @@ -68,8 +70,8 @@ class Memcached */ public function has($name) { - $name = $this->options['prefix'] . $name; - return $this->handler->get($name) ? true : false; + $key = $this->getCacheKey($name); + return $this->handler->get($key) ? true : false; } /** @@ -81,7 +83,7 @@ class Memcached */ public function get($name, $default = false) { - $result = $this->handler->get($this->options['prefix'] . $name); + $result = $this->handler->get($this->getCacheKey($name)); return false !== $result ? $result : $default; } @@ -98,9 +100,13 @@ class Memcached if (is_null($expire)) { $expire = $this->options['expire']; } - $name = $this->options['prefix'] . $name; + if ($this->tag && !$this->has($name)) { + $first = true; + } + $key = $this->getCacheKey($name); $expire = 0 == $expire ? 0 : $_SERVER['REQUEST_TIME'] + $expire; - if ($this->handler->set($name, $value, $expire)) { + if ($this->handler->set($key, $value, $expire)) { + isset($first) && $this->setTagItem($key); return true; } return false; @@ -115,8 +121,8 @@ class Memcached */ public function inc($name, $step = 1) { - $name = $this->options['prefix'] . $name; - return $this->handler->increment($name, $step); + $key = $this->getCacheKey($name); + return $this->handler->increment($key, $step); } /** @@ -128,9 +134,9 @@ class Memcached */ public function dec($name, $step = 1) { - $name = $this->options['prefix'] . $name; - $value = $this->handler->get($name) - $step; - $res = $this->handler->set($name, $value); + $key = $this->getCacheKey($name); + $value = $this->handler->get($key) - $step; + $res = $this->handler->set($key, $value); if (!$res) { return false; } else { @@ -146,19 +152,27 @@ class Memcached */ public function rm($name, $ttl = false) { - $name = $this->options['prefix'] . $name; + $key = $this->getCacheKey($name); return false === $ttl ? - $this->handler->delete($name) : - $this->handler->delete($name, $ttl); + $this->handler->delete($key) : + $this->handler->delete($key, $ttl); } /** * 清除缓存 * @access public + * @param string $tag 标签名 * @return bool */ - public function clear() + public function clear($tag = null) { + if ($tag) { + // 指定标签清除 + $keys = $this->getTagItem($tag); + $this->handler->deleteMulti($keys); + $this->rm('tag_' . md5($tag)); + return true; + } return $this->handler->flush(); } } diff --git a/core/library/think/cache/driver/Redis.php b/core/library/think/cache/driver/Redis.php index 4caa3fb8..cd33523f 100644 --- a/core/library/think/cache/driver/Redis.php +++ b/core/library/think/cache/driver/Redis.php @@ -11,6 +11,8 @@ namespace think\cache\driver; +use think\cache\Driver; + /** * Redis缓存驱动,适合单机部署、有前端代理实现高可用的场景,性能最好 * 有需要在业务层实现读写分离、或者使用RedisCluster的需求,请使用Redisd驱动 @@ -18,7 +20,7 @@ namespace think\cache\driver; * 要求安装phpredis扩展:https://github.com/nicolasff/phpredis * @author 尘缘 <130775@qq.com> */ -class Redis +class Redis extends Driver { protected $handler = null; protected $options = [ @@ -61,7 +63,7 @@ class Redis */ public function has($name) { - return $this->handler->get($this->options['prefix'] . $name) ? true : false; + return $this->handler->get($this->getCacheKey($name)) ? true : false; } /** @@ -73,7 +75,7 @@ class Redis */ public function get($name, $default = false) { - $value = $this->handler->get($this->options['prefix'] . $name); + $value = $this->handler->get($this->getCacheKey($name)); if (is_null($value)) { return $default; } @@ -95,14 +97,18 @@ class Redis if (is_null($expire)) { $expire = $this->options['expire']; } - $name = $this->options['prefix'] . $name; + if ($this->tag && !$this->has($name)) { + $first = true; + } + $key = $this->getCacheKey($name); //对数组/对象数据进行缓存处理,保证数据完整性 byron sampson $value = (is_object($value) || is_array($value)) ? json_encode($value) : $value; if (is_int($expire) && $expire) { - $result = $this->handler->setex($name, $expire, $value); + $result = $this->handler->setex($key, $expire, $value); } else { - $result = $this->handler->set($name, $value); + $result = $this->handler->set($key, $value); } + isset($first) && $this->setTagItem($key); return $result; } @@ -115,8 +121,8 @@ class Redis */ public function inc($name, $step = 1) { - $name = $this->options['prefix'] . $name; - return $this->handler->incrby($name, $step); + $key = $this->getCacheKey($name); + return $this->handler->incrby($key, $step); } /** @@ -128,8 +134,8 @@ class Redis */ public function dec($name, $step = 1) { - $name = $this->options['prefix'] . $name; - return $this->handler->decrby($name, $step); + $key = $this->getCacheKey($name); + return $this->handler->decrby($key, $step); } /** @@ -140,16 +146,26 @@ class Redis */ public function rm($name) { - return $this->handler->delete($this->options['prefix'] . $name); + return $this->handler->delete($this->getCacheKey($name)); } /** * 清除缓存 * @access public + * @param string $tag 标签名 * @return boolean */ - public function clear() + public function clear($tag = null) { + if ($tag) { + // 指定标签清除 + $keys = $this->getTagItem($tag); + foreach ($keys as $key) { + $this->handler->delete($key); + } + $this->rm('tag_' . md5($tag)); + return true; + } return $this->handler->flushDB(); } diff --git a/core/library/think/cache/driver/Sqlite.php b/core/library/think/cache/driver/Sqlite.php index a7cbfa01..0b774a1a 100644 --- a/core/library/think/cache/driver/Sqlite.php +++ b/core/library/think/cache/driver/Sqlite.php @@ -11,13 +11,14 @@ namespace think\cache\driver; +use think\cache\Driver; use think\Exception; /** * Sqlite缓存驱动 * @author liu21st */ -class Sqlite +class Sqlite extends Driver { protected $options = [ @@ -46,6 +47,17 @@ class Sqlite $this->handler = $func($this->options['db']); } + /** + * 获取实际的缓存标识 + * @access public + * @param string $name 缓存名 + * @return string + */ + protected function getCacheKey($name) + { + return $this->options['prefix'] . sqlite_escape_string($name); + } + /** * 判断缓存 * @access public @@ -54,7 +66,7 @@ class Sqlite */ public function has($name) { - $name = $this->options['prefix'] . sqlite_escape_string($name); + $name = $this->getCacheKey($name); $sql = 'SELECT value FROM ' . $this->options['table'] . ' WHERE var=\'' . $name . '\' AND (expire=0 OR expire >' . $_SERVER['REQUEST_TIME'] . ') LIMIT 1'; $result = sqlite_query($this->handler, $sql); return sqlite_num_rows($result); @@ -69,7 +81,7 @@ class Sqlite */ public function get($name, $default = false) { - $name = $this->options['prefix'] . sqlite_escape_string($name); + $name = $this->getCacheKey($name); $sql = 'SELECT value FROM ' . $this->options['table'] . ' WHERE var=\'' . $name . '\' AND (expire=0 OR expire >' . $_SERVER['REQUEST_TIME'] . ') LIMIT 1'; $result = sqlite_query($this->handler, $sql); if (sqlite_num_rows($result)) { @@ -93,7 +105,7 @@ class Sqlite */ public function set($name, $value, $expire = null) { - $name = $this->options['prefix'] . sqlite_escape_string($name); + $name = $this->getCacheKey($name); $value = sqlite_escape_string(serialize($value)); if (is_null($expire)) { $expire = $this->options['expire']; @@ -103,7 +115,13 @@ class Sqlite //数据压缩 $value = gzcompress($value, 3); } - $sql = 'REPLACE INTO ' . $this->options['table'] . ' (var, value,expire) VALUES (\'' . $name . '\', \'' . $value . '\', \'' . $expire . '\')'; + if ($this->tag) { + $tag = $this->tag; + $this->tag = null; + } else { + $tag = ''; + } + $sql = 'REPLACE INTO ' . $this->options['table'] . ' (var, value, expire, tag) VALUES (\'' . $name . '\', \'' . $value . '\', \'' . $expire . '\', \'' . $tag . '\')'; if (sqlite_query($this->handler, $sql)) { return true; } @@ -152,7 +170,7 @@ class Sqlite */ public function rm($name) { - $name = $this->options['prefix'] . sqlite_escape_string($name); + $name = $this->getCacheKey($name); $sql = 'DELETE FROM ' . $this->options['table'] . ' WHERE var=\'' . $name . '\''; sqlite_query($this->handler, $sql); return true; @@ -161,12 +179,19 @@ class Sqlite /** * 清除缓存 * @access public + * @param string $tag 标签名 * @return boolean */ - public function clear() + public function clear($tag = null) { + if ($tag) { + $name = sqlite_escape_string($tag); + $sql = 'DELETE FROM ' . $this->options['table'] . ' WHERE tag=\'' . $name . '\''; + sqlite_query($this->handler, $sql); + return true; + } $sql = 'DELETE FROM ' . $this->options['table']; sqlite_query($this->handler, $sql); - return; + return true; } } diff --git a/core/library/think/cache/driver/Wincache.php b/core/library/think/cache/driver/Wincache.php index 77fb74a4..36fe3bea 100644 --- a/core/library/think/cache/driver/Wincache.php +++ b/core/library/think/cache/driver/Wincache.php @@ -11,19 +11,22 @@ namespace think\cache\driver; +use think\cache\Driver; use think\Exception; /** * Wincache缓存驱动 * @author liu21st */ -class Wincache +class Wincache extends Driver { protected $options = [ 'prefix' => '', 'expire' => 0, ]; + protected $tag; + /** * 架构函数 * @param array $options 缓存参数 @@ -48,8 +51,8 @@ class Wincache */ public function has($name) { - $name = $this->options['prefix'] . $name; - return wincache_ucache_exists($name); + $key = $this->getCacheKey($name); + return wincache_ucache_exists($key); } /** @@ -61,8 +64,8 @@ class Wincache */ public function get($name, $default = false) { - $name = $this->options['prefix'] . $name; - return wincache_ucache_exists($name) ? wincache_ucache_get($name) : $default; + $key = $this->getCacheKey($name); + return wincache_ucache_exists($key) ? wincache_ucache_get($key) : $default; } /** @@ -78,8 +81,12 @@ class Wincache if (is_null($expire)) { $expire = $this->options['expire']; } - $name = $this->options['prefix'] . $name; - if (wincache_ucache_set($name, $value, $expire)) { + $key = $this->getCacheKey($name); + if ($this->tag && !$this->has($name)) { + $first = true; + } + if (wincache_ucache_set($key, $value, $expire)) { + isset($first) && $this->setTagItem($key); return true; } return false; @@ -94,8 +101,8 @@ class Wincache */ public function inc($name, $step = 1) { - $name = $this->options['prefix'] . $name; - return wincache_ucache_inc($name, $step); + $key = $this->getCacheKey($name); + return wincache_ucache_inc($key, $step); } /** @@ -107,8 +114,8 @@ class Wincache */ public function dec($name, $step = 1) { - $name = $this->options['prefix'] . $name; - return wincache_ucache_dec($name, $step); + $key = $this->getCacheKey($name); + return wincache_ucache_dec($key, $step); } /** @@ -119,16 +126,27 @@ class Wincache */ public function rm($name) { - return wincache_ucache_delete($this->options['prefix'] . $name); + return wincache_ucache_delete($this->getCacheKey($name)); } /** * 清除缓存 * @access public + * @param string $tag 标签名 * @return boolean */ - public function clear() + public function clear($tag = null) { - return; + if ($tag) { + $keys = $this->getTagItem($tag); + foreach ($keys as $key) { + wincache_ucache_delete($key); + } + $this->rm('tag_' . md5($tag)); + return true; + } else { + return wincache_ucache_clear(); + } } + } diff --git a/core/library/think/cache/driver/Xcache.php b/core/library/think/cache/driver/Xcache.php index e012112f..6b18b3fc 100644 --- a/core/library/think/cache/driver/Xcache.php +++ b/core/library/think/cache/driver/Xcache.php @@ -11,13 +11,14 @@ namespace think\cache\driver; +use think\cache\Driver; use think\Exception; /** * Xcache缓存驱动 * @author liu21st */ -class Xcache +class Xcache extends Driver { protected $options = [ 'prefix' => '', @@ -48,8 +49,8 @@ class Xcache */ public function has($name) { - $name = $this->options['prefix'] . $name; - return xcache_isset($name); + $key = $this->getCacheKey($name); + return xcache_isset($key); } /** @@ -61,8 +62,8 @@ class Xcache */ public function get($name, $default = false) { - $name = $this->options['prefix'] . $name; - return xcache_isset($name) ? xcache_get($name) : $default; + $key = $this->getCacheKey($name); + return xcache_isset($key) ? xcache_get($key) : $default; } /** @@ -78,8 +79,12 @@ class Xcache if (is_null($expire)) { $expire = $this->options['expire']; } - $name = $this->options['prefix'] . $name; - if (xcache_set($name, $value, $expire)) { + if ($this->tag && !$this->has($name)) { + $first = true; + } + $key = $this->getCacheKey($name); + if (xcache_set($key, $value, $expire)) { + isset($first) && $this->setTagItem($key); return true; } return false; @@ -94,8 +99,8 @@ class Xcache */ public function inc($name, $step = 1) { - $name = $this->options['prefix'] . $name; - return xcache_inc($name, $step); + $key = $this->getCacheKey($name); + return xcache_inc($key, $step); } /** @@ -107,8 +112,8 @@ class Xcache */ public function dec($name, $step = 1) { - $name = $this->options['prefix'] . $name; - return xcache_dec($name, $step); + $key = $this->getCacheKey($name); + return xcache_dec($key, $step); } /** @@ -119,16 +124,26 @@ class Xcache */ public function rm($name) { - return xcache_unset($this->options['prefix'] . $name); + return xcache_unset($this->getCacheKey($name)); } /** * 清除缓存 * @access public + * @param string $tag 标签名 * @return boolean */ - public function clear() + public function clear($tag = null) { + if ($tag) { + // 指定标签清除 + $keys = $this->getTagItem($tag); + foreach ($keys as $key) { + xcache_unset($key); + } + $this->rm('tag_' . md5($tag)); + return true; + } if (function_exists('xcache_unset_by_prefix')) { return xcache_unset_by_prefix($this->options['prefix']); } else { diff --git a/core/library/think/db/Connection.php b/core/library/think/db/Connection.php index bbdbdc6a..dea797d2 100644 --- a/core/library/think/db/Connection.php +++ b/core/library/think/db/Connection.php @@ -37,8 +37,6 @@ abstract class Connection /** @var string 当前SQL指令 */ protected $queryStr = ''; - // 最后插入ID - protected $lastInsID; // 返回或者影响记录数 protected $numRows = 0; // 事务指令数 @@ -699,10 +697,7 @@ abstract class Connection */ public function getLastInsID($sequence = null) { - if (is_null($this->lastInsID)) { - $this->lastInsID = $this->linkID->lastInsertId($sequence); - } - return $this->lastInsID; + return $this->linkID->lastInsertId($sequence); } /** diff --git a/core/library/think/db/Query.php b/core/library/think/db/Query.php index 3a687f13..0ebea9ad 100644 --- a/core/library/think/db/Query.php +++ b/core/library/think/db/Query.php @@ -1768,12 +1768,18 @@ class Query public function update(array $data) { $options = $this->parseExpress(); + $pk = $this->getPk($options); + if (isset($options['cache']) && is_string($options['cache'])) { + $key = $options['cache']; + } + if (empty($options['where'])) { - $pk = $this->getPk($options); // 如果存在主键数据 则自动作为更新条件 if (is_string($pk) && isset($data[$pk])) { $where[$pk] = $data[$pk]; - $key = 'think:' . $options['table'] . '|' . $data[$pk]; + if (!isset($key)) { + $key = 'think:' . $options['table'] . '|' . $data[$pk]; + } unset($data[$pk]); } elseif (is_array($pk)) { // 增加复合主键支持 @@ -1793,6 +1799,8 @@ class Query } else { $options['where']['AND'] = $where; } + } elseif (is_string($pk) && isset($options['where']['AND'][$pk]) && is_scalar($options['where']['AND'][$pk])) { + $key = 'think:' . $options['table'] . '|' . $options['where']['AND'][$pk]; } // 生成UPDATE SQL语句 $sql = $this->builder()->update($data, $options); @@ -2037,7 +2045,7 @@ class Query public function chunk($count, $callback, $column = null) { $options = $this->getOptions(); - $column = $column ?: $this->getPk(); + $column = $column ?: $this->getPk(isset($options['table']) ? $options['table'] : ''); $bind = $this->bind; $resultSet = $this->limit($count)->order($column, 'asc')->select(); @@ -2093,9 +2101,12 @@ class Query { // 分析查询表达式 $options = $this->parseExpress(); + if (isset($options['cache']) && is_string($options['cache'])) { + $key = $options['cache']; + } if (!is_null($data) && true !== $data) { - if (!is_array($data)) { + if (!isset($key) && !is_array($data)) { // 缓存标识 $key = 'think:' . $options['table'] . '|' . $data; } diff --git a/core/library/think/log/driver/File.php b/core/library/think/log/driver/File.php index 11b265a2..bb6844a9 100644 --- a/core/library/think/log/driver/File.php +++ b/core/library/think/log/driver/File.php @@ -58,7 +58,7 @@ class File } $runtime = number_format(microtime(true) - THINK_START_TIME, 10); - $reqs = number_format(1 / $runtime, 2); + $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]'; diff --git a/core/library/think/log/driver/Socket.php b/core/library/think/log/driver/Socket.php index 51b0fa56..f24b6091 100644 --- a/core/library/think/log/driver/Socket.php +++ b/core/library/think/log/driver/Socket.php @@ -64,7 +64,7 @@ class Socket return false; } $runtime = number_format(microtime(true) - THINK_START_TIME, 10); - $reqs = number_format(1 / $runtime, 2); + $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]'; diff --git a/core/tpl/think_exception.tpl b/core/tpl/think_exception.tpl index a978f1de..37b53999 100644 --- a/core/tpl/think_exception.tpl +++ b/core/tpl/think_exception.tpl @@ -86,7 +86,7 @@ body { color: #333; font: 16px Verdana, "Helvetica Neue", helvetica, Arial, 'Microsoft YaHei', sans-serif; - margin: 0px; + margin: 0; padding: 0 20px 20px; } h1{ @@ -246,7 +246,7 @@ .exception-var table td{ padding: 0 6px; vertical-align: top; - word-break: break-word; + word-break: break-all; } .exception-var table td:first-child{ width: 12px; @@ -502,4 +502,4 @@ - \ No newline at end of file +