/** * 定义析构函数 自动释放获得的锁 */ public function __destruct() { foreach (self::$lockCache as $key => $islock) { if ($islock) { Model::getInstance()->cache($this->userCache)->getInstance()->delete($key); unset(self::$lockCache[$key]); } } }
/** * 上锁 * * @param string $key 要上的锁的key * @param bool $wouldblock 是否堵塞 * * @return mixed */ public function lock($key, $wouldblock = false) { if (empty($key)) { return false; } $key = $this->getKey($key); if (isset(self::$lockCache[$key]) && self::$lockCache[$key] == Model::getInstance()->cache($this->userCache)->getInstance()->get($key)) { return true; } $driverType = Model::getInstance()->cache($this->userCache)->getDriverType(); if ($driverType === 1) { //memcached $isLock = Model::getInstance()->cache($this->userCache)->getInstance()->add($key, (string) Cml::$nowMicroTime, $this->expire); } else { //memcache $isLock = Model::getInstance()->cache($this->userCache)->getInstance()->add($key, (string) Cml::$nowMicroTime, 0, $this->expire); } if ($isLock) { self::$lockCache[$key] = (string) Cml::$nowMicroTime; return true; } //非堵塞模式 if (!$wouldblock) { return false; } //堵塞模式 do { usleep(200); if ($driverType === 1) { //memcached $isLock = Model::getInstance()->cache($this->userCache)->getInstance()->add($key, (string) Cml::$nowMicroTime, $this->expire); } else { //memcache $isLock = Model::getInstance()->cache($this->userCache)->getInstance()->add($key, (string) Cml::$nowMicroTime, 0, $this->expire); } } while (!$isLock); self::$lockCache[$key] = (string) Cml::$nowMicroTime; return true; }
/** * 上锁 * * @param string $key * @param bool $wouldblock 是否堵塞 * * @return mixed */ public function lock($key, $wouldblock = false) { if (empty($key)) { return false; } $key = $this->getKey($key); if (isset(self::$lockCache[$key]) && self::$lockCache[$key] == Model::getInstance()->cache($this->userCache)->getInstance()->get($key)) { return true; } if (Model::getInstance()->cache($this->userCache)->getInstance()->set($key, Cml::$nowMicroTime, array('nx', 'ex' => $this->expire))) { self::$lockCache[$key] = (string) Cml::$nowMicroTime; return true; } //非堵塞模式 if (!$wouldblock) { return false; } //堵塞模式 do { usleep(200); } while (!Model::getInstance()->cache($this->userCache)->getInstance()->set($key, Cml::$nowMicroTime, array('nx', 'ex' => $this->expire))); self::$lockCache[$key] = (string) Cml::$nowMicroTime; return true; }
/** * 设置cache版本号 * * @param $table */ public function setCacheVer($table) { Model::getInstance()->cache()->set('db_cache_version_' . $table, microtime(true), $this->conf['cache_expire']); }
/** * 获取多条数据 * * @param int $offset 偏移量 * @param int $limit 返回的条数 * @param bool $useMaster 是否使用主库 默认读取从库 * * @return array */ public function select($offset = null, $limit = null, $useMaster = false) { is_null($offset) || $this->limit($offset, $limit); $this->sql['columns'] == '' && ($this->sql['columns'] = '*'); $columns = $this->sql['columns']; $table = $operator = $cacheKey = ''; foreach ($this->table as $key => $val) { $realTable = $this->getRealTableName($key); $cacheKey .= $this->getCacheVer($realTable); $on = null; if (isset($this->join[$key])) { $operator = ' INNER JOIN'; $on = $this->join[$key]; } elseif (isset($this->leftJoin[$key])) { $operator = ' LEFT JOIN'; $on = $this->leftJoin[$key]; } elseif (isset($this->rightJoin[$key])) { $operator = ' RIGHT JOIN'; $on = $this->rightJoin[$key]; } else { empty($table) || ($operator = ' ,'); } if (is_null($val)) { $table .= "{$operator} `{$realTable}`"; } else { $table .= "{$operator} `{$realTable}` AS `{$val}`"; } is_null($on) || ($table .= " ON {$on}"); } if (empty($table)) { throw new \InvalidArgumentException(Lang::get('_PARSE_SQL_ERROR_NO_TABLE_', 'select')); } empty($this->sql['limit']) && ($this->sql['limit'] = "LIMIT 0, 100"); $sql = "SELECT {$columns} FROM {$table} " . $this->sql['where'] . $this->sql['groupBy'] . $this->sql['having'] . $this->sql['orderBy'] . $this->union . $this->sql['limit']; $cacheKey = md5($sql . json_encode($this->bindParams)) . $cacheKey; $return = Model::getInstance()->cache()->get($cacheKey); if ($return === false) { $stmt = $this->prepare($sql, $useMaster ? $this->wlink : $this->rlink); $this->execute($stmt); $return = $stmt->fetchAll(\PDO::FETCH_ASSOC); Model::getInstance()->cache()->set($cacheKey, $return, $this->conf['cache_expire']); } else { if (Cml::$debug) { $this->currentSql = $sql; $this->debugLogSql(Debug::SQL_TYPE_FROM_CACHE); $this->currentSql = ''; } $this->reset(); $this->clearBindParams(); } return $return; }
/** * 登出 * */ public static function logout() { $user = Acl::getLoginInfo(); $user && Model::getInstance()->cache()->delete("SSOSingleSignOn" . $user['id']); Cookie::delete(Config::get('userauthid')); }
/** * 定义析构函数 自动释放获得的锁 * */ public function __destruct() { foreach ($this->lockCache as $key => $isMyLock) { if ($isMyLock == Model::getInstance()->cache($this->useCache)->getInstance()->get($key)) { Model::getInstance()->cache($this->useCache)->getInstance()->delete($key); } $this->lockCache[$key] = null; //防止gc延迟,判断有误 unset($this->lockCache[$key]); } }
/** * 获取模型方法 * * @return \Cml\Model */ public function model() { return Model::getInstance(); }
/** * 设置cache版本号 * * @param string $table */ public function setCacheVer($table) { $isOpenEmergencyMode = Config::get('emergency_mode_not_real_time_refresh_mysql_query_cache'); if ($isOpenEmergencyMode !== false && $isOpenEmergencyMode > 0) { //开启了紧急模式 $expireTime = Model::getInstance()->cache()->get("emergency_mode_not_real_time_refresh_mysql_query_cache_{$table}"); if ($expireTime && $isOpenEmergencyMode + $expireTime > time()) { return; } Model::getInstance()->cache()->set("emergency_mode_not_real_time_refresh_mysql_query_cache_{$table}", time(), 3600); } Model::getInstance()->cache()->set($this->conf['mark'] . '_db_cache_version_' . $table, microtime(true), $this->conf['cache_expire']); }
/** * 校验验证码 * * @param bool $isCn 是否为中文验证码 * @param string $input 用户输入 * @param string $verifyName 生成验证码时的字段 * * @return bool 正确返回true,错误返回false */ public static function checkCode($input, $isCn = false, $verifyName = 'verifyCode') { $key = \Cml\Http\Cookie::get($verifyName); if (!$key) { return false; } $code = \Cml\Model::getInstance()->cache()->get($key); \Cml\Model::getInstance()->cache()->delete($key); $isCn && ($input = md5(urldecode($input))); if ($code === false || $code != $input) { return false; } else { return true; } }
/** * 获取有权限的菜单列表 * * @return array */ public static function getMenus() { $res = array(); $authInfo = self::getLoginInfo(); if (!$authInfo) { return $res; } //登录超时 Model::getInstance()->db()->table(array('menus' => 'm'))->columns(array('m.id', 'm.pid', 'm.title', 'm.url')); //当前登录用户是否为超级管理员 if (Config::get('administratorid') !== intval($authInfo['id'])) { Model::getInstance()->db()->join(array('access' => 'a'), 'a.menuid=m.id')->lBrackets()->where('a.groupid', $authInfo['groupid'])->_or()->where('a.userid', $authInfo['id'])->rBrackets()->_and(); } $result = Model::getInstance()->db()->where('m.isshow', 1)->orderBy('m.sort', 'DESC')->orderBy('m.id', 'ASC')->limit(0, 2000)->select(); $res = Tree::getTreeNoFormat($result, 0); return $res; }
/** * 任意等级的日志记录 * * @param mixed $level 日志等级 * @param string $message 要记录到log的信息 * @param array $context 上下文信息 * * @return null */ public function log($level, $message, array $context = []) { return Model::getInstance()->cache(Config::get('redis_log_use_cache'))->getInstance()->lPush(Config::get('log_prefix') . '_' . $level, $this->format($message, $context)); }
/** * 返回驱动 * * @return \Redis */ private function getDriver() { return Model::getInstance()->cache(Config::get('queue_use_cache'))->getInstance(); }
/** * 获取多条数据 * * @param int $offset 偏移量 * @param int $limit 返回的条数 * @param bool $useMaster 是否使用主库 默认读取从库 * * @return array */ public function select($offset = null, $limit = null, $useMaster = false) { list($sql, $cacheKey) = $this->buildSql($offset, $limit, true); if ($this->openCache) { $cacheKey = md5($sql . json_encode($this->bindParams)) . implode('', $cacheKey); $return = Model::getInstance()->cache()->get($cacheKey); } else { $return = false; } if ($return === false) { $stmt = $this->prepare($sql, $useMaster ? $this->wlink : $this->rlink); $this->execute($stmt); $return = $stmt->fetchAll(\PDO::FETCH_ASSOC); $this->openCache && Model::getInstance()->cache()->set($cacheKey, $return, $this->conf['cache_expire']); } else { if (Cml::$debug) { $this->currentSql = $sql; $this->debugLogSql(Debug::SQL_TYPE_FROM_CACHE); $this->currentSql = ''; } $this->reset(); $this->clearBindParams(); } return $return; }
/** * 返回驱动 * * @return \Redis */ private function getDriver() { return Model::getInstance()->cache($this->useCache)->getInstance(); }
/** * 获取多条数据 * * @return array */ public function select() { $this->sql['columns'] == '' && ($this->sql['columns'] = '*'); $columns = $this->sql['columns'] == '*' ? Config::get('db_fields_cache') ? $this->getDbFields($this->getRealTableName(key($this->table)), null, 1) : '*' : $this->sql['columns']; $table = $operator = $cacheKey = ''; foreach ($this->table as $key => $val) { $realTable = $this->getRealTableName($key); $cacheKey .= $this->getCacheVer($realTable); $on = null; if (isset($this->join[$key])) { $operator = ' INNER JOIN'; $on = $this->join[$key]; } elseif (isset($this->leftJoin[$key])) { $operator = ' LEFT JOIN'; $on = $this->leftJoin[$key]; } elseif (isset($this->rightJoin[$key])) { $operator = ' RIGHT JOIN'; $on = $this->rightJoin[$key]; } else { empty($table) || ($operator = ' ,'); } if (is_null($val)) { $table .= "{$operator} `{$realTable}`"; } else { $table .= "{$operator} `{$realTable}` AS `{$val}`"; } is_null($on) || ($table .= " ON {$on}"); } empty($table) && \Cml\throwException(Lang::get('_PARSE_SQL_ERROR_NO_TABLE_', 'select')); empty($this->sql['limit']) && ($this->sql['limit'] = "LIMIT 0, 100"); $sql = "SELECT {$columns} FROM {$table} " . $this->sql['where'] . $this->sql['groupBy'] . $this->sql['having'] . $this->sql['orderBy'] . $this->sql['limit'] . $this->union; $cacheKey = md5($sql . json_encode($this->bindParams)) . $cacheKey; $return = Model::getInstance()->cache()->get($cacheKey); if ($return === false) { $stmt = $this->prepare($sql, $this->rlink); $this->execute($stmt); $return = $stmt->fetchAll(\PDO::FETCH_ASSOC); Model::getInstance()->cache()->set($cacheKey, $return, $this->conf['cache_expire']); } else { $this->reset(); $this->bindParams = array(); } return $return; }