/** * 单例模式,获取一个指定的实例 * * // 加载默认实例 * $db = Database::instance(); * * // 指定实例名称和配置 * $db = Database::instance('custom', $config); * * @param string $name 实例名 * @param array $config 配置参数 * @return Connection */ public static function instance($name = null, array $config = null) { if (null === $name) { $name = Db::$default; } if (!isset(Db::$instances[$name])) { // 读取配置 if (null === $config) { $config = (array) Config::load(self::$configFile)->get($name); Base::getLog()->debug(__METHOD__ . ' get default config', ['name' => $name]); } // 合并默认配置 if (isset(self::$defaultConfig[Arr::get($config, 'driver')])) { $config = Arr::merge(self::$defaultConfig[Arr::get($config, 'driver')], $config); Base::getLog()->debug(__METHOD__ . ' merge config', ['name' => $name]); } $conn = DriverManager::getConnection($config); Base::getLog()->debug(__METHOD__ . ' create dbal connection', ['name' => $name]); // 额外注册字段类型 if (isset(self::$mappingType[Arr::get($config, 'driver')])) { $platform = $conn->getDatabasePlatform(); foreach (self::$mappingType[Arr::get($config, 'driver')] as $dbType => $doctrineType) { if (!$platform->hasDoctrineTypeMappingFor($dbType)) { Base::getLog()->debug(__METHOD__ . ' add dbal mapping type', ['raw' => $dbType, 'dbal' => $doctrineType]); $platform->registerDoctrineTypeMapping($dbType, $doctrineType); } } } Db::$instances[$name] = $conn; Base::getLog()->debug(__METHOD__ . ' save db instance', ['name' => $name]); } return Db::$instances[$name]; }
/** * 读取消息文本 * * // 读取message/text.php中的username * $username = Message::load('text', 'username'); * * @param string $file 文件名 * @param string $path 键名 * @param mixed $default 键名不存在时返回默认值 * @return string|array 内容,如果$path为空的话,就返回完整数组内容 */ public static function load($file, $path = null, $default = null) { static $messages; if (!isset($messages[$file])) { $messages[$file] = []; $files = []; foreach (self::$_messagePaths as $includePath) { if (is_file($includePath . $file . self::$ext)) { $files[] = $includePath . $file . self::$ext; } } if (!empty($files)) { foreach ($files as $f) { $messages[$file] = Arr::merge($messages[$file], Base::load($f)); } } } if (null === $path) { // 返回完整的数组 return $messages[$file]; } else { // 返回指定的键名 return Arr::path($messages[$file], $path, $default); } }
/** * @param string $text 明文 * @param string $hashType 加密方式 * @param array $extra 附加参数 * @return string */ public static function hash($text, $hashType = self::MD5_HASH, array $extra = null) { $params = Arr::merge(['text' => $text], (array) $extra); switch ($hashType) { case self::MD5_HASH: $object = new MD5($params); break; case self::SHA1_HASH: $object = new SHA1($params); break; case self::MD5_TWICE_HASH: $object = new MD5Twice($params); break; case self::PASS_SALT_MD5_HASH: $object = new Joomla($params); break; case self::SALT_PASS_MD5_HASH: $object = new osCommerce($params); break; default: $object = new Plain($params); } /** @var HashInterface $object */ return (string) $object->hash(); }
/** * 初始化数据构造器 * * @param int $type 要执行的SQL类型 * @return $this */ protected function _build($type) { switch ($type) { case Db::SELECT: $this->_dbBuilder = $this->_db->createQueryBuilder()->select(); break; case Db::UPDATE: $this->_dbBuilder = $this->_db->createQueryBuilder()->update($this->_tableName, $this->_objectName); break; case Db::DELETE: $this->_dbBuilder = $this->_db->createQueryBuilder()->delete($this->_tableName); } $selectList = []; foreach ($this->_dbPending as $method) { $name = $method['name']; $args = $method['args']; // 如果是select,那么暂时先不执行 if ($name == 'select') { $selectList = Arr::merge($selectList, $args); continue; } $this->_dbApplied[$name] = $name; call_user_func_array([$this->_dbBuilder, $name], $args); } $this->_dbBuilder->select($selectList); return $this; }
/** * 执行检测 * * if ($validation->check()) * { * // 校验通过 * } * * @return bool */ public function check() { // 清空数据和错误 $data = $this->_errors = []; // 保存原来的数据 $original = $this->_data; // 读取字段信息 $fields = Arr::merge(array_keys($original), array_keys($this->_labels)); // 现在的规则 $rules = $this->_rules; // 逐个字段格式化下规则 foreach ($fields as $field) { $data[$field] = Arr::get($this->_data, $field); // 如果key为true,那么规则就是所有字段都生效 if (isset($rules[true])) { if (!isset($rules[$field])) { $rules[$field] = []; } $rules[$field] = array_merge($rules[$field], $rules[true]); } } // 保存格式化后的规则 $this->_data = $data; // 清空全局规则 unset($rules[true]); // 绑定一些必要的变量 $this->bind(':validation', $this); $this->bind(':data', $this->_data); foreach ($rules as $field => $set) { $value = Arr::get($this->_data, $field); // 绑定当前处理的字段和值 $this->bind([':field' => $field, ':value' => $value]); foreach ($set as $array) { // 格式:[$rule, $params] $rule = array_shift($array); $params = array_shift($array); foreach ($params as $key => $param) { // 替换绑定的变量 if (is_string($param) && array_key_exists($param, $this->_bound)) { $params[$key] = $this->_bound[$param]; } } // 默认错误名跟规则名一致,因为一般规则都是字符串表示的 $errorName = $rule; // 规则是数组,说明传入的是一个callback if (is_array($rule)) { // 允许rule('field', [':model', 'some_rule']); if (is_string($rule[0]) && array_key_exists($rule[0], $this->_bound)) { $rule[0] = $this->_bound[$rule[0]]; } // 把索引为1的值作为错误标记 $errorName = $rule[1]; $passed = call_user_func_array($rule, $params); } elseif (!is_string($rule)) { // 匿名函数不做错误处理,留待内容做处理 $errorName = false; $passed = call_user_func_array($rule, $params); } elseif (method_exists(self::$validHelperClass, $rule)) { // 调用校验助手类来完成操作 $method = new ReflectionMethod(self::$validHelperClass, $rule); $passed = $method->invokeArgs(null, $params); } elseif (false === strpos($rule, '::')) { // 不符合静态方法调用的规则,那么直接按照函数调用 $function = new ReflectionFunction($rule); $passed = $function->invokeArgs($params); } else { // 当做一次静态函数调用 $temp = explode('::', $rule, 2); $class = array_shift($temp); $method = array_shift($temp); $method = new ReflectionMethod($class, $method); $passed = $method->invokeArgs(null, $params); } if (!in_array($rule, $this->_emptyRules) && !Valid::notEmpty($value)) { continue; } if (false === $passed && false !== $errorName) { $this->error($field, $errorName, $params); break; } elseif (isset($this->_errors[$field])) { // 匿名函数自己处理错误信息,这里就不处理了 break; } } } // 还原原来的值 $this->_data = $original; return empty($this->_errors); }
/** * {@inheritdoc} */ public function withAddedHeader($name, $value) { if (isset($this->_headers[$name])) { // 如果是数组,那么合并 if (is_array($value)) { $this->_headers[$name] = Arr::merge($this->_headers[$name], $value); } else { $this->_headers[$name][] = $value; } } else { $this->withHeader($name, $value); } return $this; }
/** * 设置模板解析选项 * * @param array $options */ public function setOptions(array $options) { $this->_templateOptions = Arr::merge($this->_templateOptions, $options); }
/** * 返回指定变量的字符串格式 * * // 返回"?sort=title&limit=10" * $query = Url::query(['sort' => 'title', 'limit' => 10]); * * [!!] 参数中带null的话,这个键会被忽略 * * @param array $params 参数列表Array of GET parameters * @param bool $useGet 是否合并当前的$_GET数组 * @return string */ public static function query(array $params = null, $useGet = false) { if ($useGet) { if (null === $params) { $params = $_GET; } else { $params = Arr::merge($_GET, $params); } } if (empty($params)) { return ''; } $query = http_build_query($params, '', '&'); return $query === '' ? '' : '?' . $query; }
/** * 检验[Arr::merge]的功能 * * @dataProvider dataMerge * @param mixed $arr1 * @param mixed $arr2 * @param mixed $expected */ public function testMerge($arr1, $arr2, $expected) { $this->assertEquals($expected, Arr::merge($arr1, $arr2)); }
/** * 编码,增加HTTP头 * 覆盖原方法,自定义Server段 * * @param string $content * @param TcpConnection $connection * @return string */ public static function encode($content, TcpConnection $connection) { $headers = HttpCache::$header; Base::getLog()->debug(__METHOD__ . ' encode header and send', ['headers' => $headers]); $sendHeader = []; // 没有http-code默认给个,content-type也是 $hasStatus = false; $hasContentType = false; foreach ($headers as $header) { if (substr($header, 0, strlen('HTTP/')) == 'HTTP/') { $hasStatus = true; $sendHeader[] = $header; Base::getLog()->debug(__METHOD__ . ' custom http code', ['header' => $header]); } elseif (strtolower(substr($header, 0, strlen('content-type:'))) == 'content-type:') { $hasContentType = true; } } if (!$hasStatus) { $sendHeader[] = "HTTP/1.1 200 OK"; Base::getLog()->debug(__METHOD__ . ' default http code'); } if (!$hasContentType) { Base::getLog()->debug(__METHOD__ . ' missing content type, set default value'); $sendHeader[] = 'Content-Type: text/html;charset=utf-8'; } // 合并 $sendHeader = Arr::merge($sendHeader, $headers); // 一些额外的header信息 if (Base::$expose) { $sendHeader[] = "Server: tourze/" . Base::VERSION; } $sendHeader[] = "Content-Length: " . strlen($content); // 记录要输出的header Base::getLog()->debug(__METHOD__ . ' final send header', $sendHeader); $sendHeader = implode("\r\n", $sendHeader); $sendHeader .= "\r\n\r\n"; // save session self::sessionWriteClose(); HttpCache::$header = []; // the whole http package return $sendHeader . $content; }