连接数据库方法
@access public
@param array         $config 连接参数
@param integer       $linkNum 连接序号
@param array|bool    $autoConnection 是否自动连接主数据库（用于分布式）
@return PDO
@throws Exception
181017
public function connect(array $config = [], $linkNum = 0, $autoConnection = false)
    {
        if (isset($this->links[$linkNum])) {
            return $this->links[$linkNum];
        }

        if (!$config) {
            $config = $this->config;
        } else {
            $config = array_merge($this->config, $config);
        }

        // 连接参数
        if (isset($config['params']) && is_array($config['params'])) {
            $params = $config['params'] + $this->params;
        } else {
            $params = $this->params;
        }

        // 记录当前字段属性大小写设置
        $this->attrCase = $params[PDO::ATTR_CASE];

        try {
            if (empty($config['dsn'])) {
                $config['dsn'] = $this->parseDsn($config);
            }

            if ($config['debug']) {
                $startTime = microtime(true);
            }

            $this->links[$linkNum] = new PDO($config['dsn'], $config['username'], $config['password'], $params);

            if ($config['debug']) {
                // 记录数据库连接信息
                $this->log('[ DB ] CONNECT:[ UseTime:' . number_format(microtime(true) - $startTime, 6) . 's ] ' . $config['dsn']);
            }

            return $this->links[$linkNum];
        } catch (\PDOException $e) {
            if ($autoConnection) {
                $this->log('[ ERR ] ' . $e->getMessage());
                return $this->connect($autoConnection, $linkNum);
            } else {
                throw $e;
            }
        }
    }
1372941
private function _belongsToMany(array $config): ResultSet
    {
        //配置信息
        $targetClass = $config['table'];  //对方表
        $middleClass = $config['middle'];  //中间表
        $selfPrimaryKey = $config['selfPrimaryKey'];//本表主键
        $targetPrimaryKey = $config['targetPrimaryKey'];//对方 表主键
        $selfForeignKey = $config['selfForeignKey'];//中间表中与本表关联的键
        $targetForeignKey = $config['targetForeignKey'];//中间表中与对方 表关联的键

        //取本表主键的值
        $primaryValue = $this->$selfPrimaryKey;
        $config['selfPrimaryValue'] = $primaryValue;

        /**
         * 中间对象表
         * @var $middleInstance Table
         */
        $middleInstance = $middleClass::instance();

        //取中间表里,对方表外键的值
        $foreignValues = $middleInstance->col($targetForeignKey, [$selfForeignKey => $primaryValue]);

        /**
         * 对方表对象
         * @var $targetInstance Table
         */
        $targetInstance = $targetClass::instance();

        //在对方对象表中查询关联记录
        return ResultSet::instance($targetInstance->select('*', [$targetPrimaryKey => $foreignValues]))
            ->_setType('belongsToMany', $config);
    }
146169
public function createConnection($dsn, array $config, array $options)
    {
        $username = array_get($config, 'username');

        $password = array_get($config, 'password');

        return new PDO($dsn, $username, $password, $options);
    }
750526
public function init(array $config = [])
    {
        $config = $config ?: $this->config;

        $isDoStart = false;
        if (isset($config['use_trans_sid'])) {
            ini_set('session.use_trans_sid', $config['use_trans_sid'] ? 1 : 0);
        }

        // 启动session
        if (!empty($config['auto_start']) && PHP_SESSION_ACTIVE != session_status()) {
            ini_set('session.auto_start', 0);
            $isDoStart = true;
        }

        if (isset($config['prefix'])) {
            $this->prefix = $config['prefix'];
        }

        if (isset($config['use_lock'])) {
            $this->lock = $config['use_lock'];
        }

        if (isset($config['var_session_id']) && isset($_REQUEST[$config['var_session_id']])) {
            session_id($_REQUEST[$config['var_session_id']]);
        } elseif (isset($config['id']) && !empty($config['id'])) {
            session_id($config['id']);
        } else {
            session_id(WorkerHttp::sessionId());
        }

        if (isset($config['name'])) {
            WorkerHttp::sessionName($config['name']);
        }

        if (isset($config['path'])) {
            WorkerHttp::sessionSavePath($config['path']);
        }

        if (isset($config['domain'])) {
            ini_set('session.cookie_domain', $config['domain']);
        }

        if (isset($config['expire'])) {
            ini_set('session.gc_maxlifetime', $config['expire']);
            ini_set('session.cookie_lifetime', $config['expire']);
        }

        if (isset($config['secure'])) {
            ini_set('session.cookie_secure', $config['secure']);
        }

        if (isset($config['httponly'])) {
            ini_set('session.cookie_httponly', $config['httponly']);
        }

        if (isset($config['use_cookies'])) {
            ini_set('session.use_cookies', $config['use_cookies'] ? 1 : 0);
        }

        if (isset($config['cache_limiter'])) {
            session_cache_limiter($config['cache_limiter']);
        }

        if (isset($config['cache_expire'])) {
            session_cache_expire($config['cache_expire']);
        }

        if (!empty($config['type'])) {
            // 读取session驱动
            $class = false !== strpos($config['type'], '\\') ? $config['type'] : '\\think\\session\\driver\\' . ucwords($config['type']);

            // 检查驱动类
            if (!class_exists($class) || !session_set_save_handler(new $class($config))) {
                throw new ClassNotFoundException('error session handler:' . $class, $class);
            }
        }

        if ($isDoStart) {
            $this->start();
        } else {
            $this->init = false;
        }

        return $this;
    }
954907
public function pdoConnect($activeConfig)
    {
        $this->activeConfig = $activeConfig;
        $dsn = 'mysql:dbname=' . $activeConfig["database"] . ';host=' . $activeConfig["host"] . ';port=' . $activeConfig['port'] ?? 3306;
        $pdo = new \PDO($dsn, $activeConfig["user"], $activeConfig["password"], [
            \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $activeConfig['charset'] ?? 'utf8'
        ]);
        $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
        $this->setPdoConnection($pdo);
        
        return $this;
    }
593700
public static function connect(ConnectionParameters $config){

		//Not static
		$con = new self();
		
		switch(\strtolower(\trim($config->getDriver()))){
			
			case 'sqlite':
				$con->Connection = new \PDO(
						\sprintf('sqlite:%s', $config->getHost()),
						$config->getUsername(),
						$config->getPassword(),
						$config->getOptions());
				break;
			
			default:
				$con->Connection = new \PDO(\sprintf(
						'%s:host=%s;charset=%s;dbname=%s',
						$config->getDriver() ? $config->getDriver() : '',
						$config->getHost() ? $config->getHost() : '',
						$config->getCharset() ? $config->getCharset() : '',
						$config->getDatabaseName() ? $config->getDatabaseName() : ''
					),
					$config->getUsername(),
					$config->getPassword(),
					$config->getOptions());
				break;
			
		}
		
		return $con;

	}
1158935
public function join($linkTableName, $relation, $fields = '*', $where = [], $orderBy = ''): Result
    {
        // 生成关联表模型对象
        $table = $this->makeTable($linkTableName);

        // 生成本表关联字段与关联表关联字段
        list ($field, $linkField) = $this->relation($relation);

        // 生成本表关联字段的所有值
        $keys = $this->getMapKeys($field);
        if (!$keys) {
            return $this;
        }

        // 生成关联表查询条件
        // $where [] = $table->markField ( $linkField ) . ' in ("' . join ( '","', $keys ) . '") ';
        $where[$linkField . ' in'] = $keys;

        // 关联表查询结果
        $linkData = $table->select($this->append($fields, $linkField), $where, $orderBy)
            ->all();

        // 生成以关联表关联字段值为键的数组
        $linkResult = [];
        foreach ($linkData as $row) {
            $key = $row[$linkField];
            if (!array_key_exists($key, $linkResult)) {
                $linkResult[$key] = [];
            }
            $linkResult[$key][] = $row;
        }

        // 转换每个值对应的结果为结果集对象
        foreach ($linkResult as $k => $v) {
            $linkResult[$k] = new Result($linkTableName, $v);
        }

        // 为本表每行数据补充字段
        foreach ($this->data as $key => $row) {

            // 如果没有对应的关联,则不扩展
            if (array_key_exists($row[$field], $linkResult)) {
                // 关联的记录
                $linkObj = $linkResult[$row[$field]];

                // 如果本表已经有此字段,则不扩展
                if (!array_key_exists($table->name(), $row)) {
                    $row[$table->alias()] = $linkObj;
                }

                $this->data[$key] = $row;
            }
        }

        $this->row2Obj();
        return $this;
    }
1086069
public function db($linkNum='',$config='',$force=false) {
        if('' === $linkNum && $this->db) {
            return $this->db;
        }

        if(!isset($this->_db[$linkNum]) || $force ) {
            // 创建一个新的实例
            if(!empty($config) && is_string($config) && false === strpos($config,'/')) { // 支持读取配置参数
                $config  =  C($config);
            }
            $this->_db[$linkNum]            =    Db::getInstance($config);
        }elseif(NULL === $config){
            $this->_db[$linkNum]->close(); // 关闭数据库连接
            unset($this->_db[$linkNum]);
            return ;
        }

        // 切换数据库连接
        $this->db   =    $this->_db[$linkNum];
        $this->_after_db();
        // 字段检测
        if(!empty($this->name) && $this->autoCheckFields)    $this->_checkTableInfo();
        return $this;
    }
776404
public static function create($id, array $config)
    {
        static::$databaseConnections[$id] = static::createDatabaseConnection($config);

        if (static::$activeDatabaseConnection === null) {
            static::select($id);
        }
    }
286101
public static function fromArray(array $config): EasyDB
    {

        /** @var string $dsn */
        $dsn      = $config[0];
        /** @var string|null $username */
        $username = $config[1] ?? null;
        /** @var string|null $password */
        $password = $config[2] ?? null;
        /** @var array $options */
        $options  = $config[3] ?? [];

        $dbEngine = '';
        $post_query = null;

        if (!\is_string($username)) {
            $username = '';
        }
        if (!\is_string($password)) {
            $password = '';
        }

        // Let's grab the DB engine
        if (strpos($dsn, ':') !== false) {
            $dbEngine = explode(':', $dsn)[0];
        }

        /** @var string $post_query */
        $post_query = '';

        // If no charset is specified, default to UTF-8
        switch ($dbEngine) {
            case 'mysql':
                if (\strpos($dsn, ';charset=') === false) {
                    $dsn .= ';charset=utf8mb4';
                }
                break;
            case 'pgsql':
                $post_query = "SET NAMES 'UNICODE'";
                break;
        }

        try {
            $pdo = new \PDO($dsn, $username, $password, $options);
        } catch (\PDOException $e) {
            if (\strpos((string) $e->getMessage(), 'could not find driver') !== false) {
                throw (new Issues\ConstructorFailed(
                    'Could not create a PDO connection. Is the driver installed/enabled?'
                ))->setRealException($e);
            }
            
            if (\strpos((string) $e->getMessage(), 'unknown database') !== false) {
                throw (new Issues\ConstructorFailed(
                    'Could not create a PDO connection. Check that your database exists.'
                ))->setRealException($e);
            }
            
            // Don't leak credentials directly if we can.
            throw (new Issues\ConstructorFailed(
                'Could not create a PDO connection. Please check your username and password.'
            ))->setRealException($e);
        }

        if (!empty($post_query)) {
            $pdo->query($post_query);
        }

        return new EasyDB($pdo, $dbEngine, $options);
    }
476232
private function _hasMany(array $config): ResultSet
    {
        //配置信息
        $tableClass = $config['table'];
        $primaryKey = $config['primaryKey'];
        $foreignKey = $config['foreignKey'];

        //取主键的值
        $primaryValue = $this->$primaryKey;

        /**
         * 子对象表
         * @var $tableInstance Table
         */
        $tableInstance = $tableClass::instance();

        //在子对象表中查询关联记录
        return ResultSet::instance($tableInstance->select('*', [$foreignKey => $primaryValue]))
            ->_setType('hasMany', $config);
    }
396784
public function setConnection($connectionConfig)
    {
        self::$config = static::parseUrl($connectionConfig);

        try {
            return  static::createConnection(self::$config);
        } catch (\PDOException $e) {
            throw new \Exception($e->getMessage());
        }
    }
485980
public static function get($config = null) {
		if (!isset($config['driver'])) {
			throw new ConnectionException("Unknown driver");
		}
		if (!isset($config['host']) || !isset($config['port'])) {
			throw new ConnectionException("Host and Port is required");
		}
		$type = $config['driver'];
		$hash = md5($type . ':' . $config['host'] . ':' . $config['port']);
		if (!isset(self::$created_driver[$hash])) {
			if (isset(self::$driver[$type])) {
				$className = self::$driver[$type];
			} else {
				$className = __NAMESPACE__ . '\\Driver\\' . ucfirst($type);
			}
			self::$created_driver[$hash] = new $className($config);
		}
		return self::$created_driver[$hash];
	}
672666
protected function validateConfiguration(array $config) : bool
    {
        if (!is_array($config)) {
            throw new DatabaseConnectionException('Could not load LDAP configuration settings.');
        }
        $config_keys = array_keys($config);
        $missing = array_diff(['server', 'port', 'domain', 'base_dn', 'username', 'password'], $config_keys);
        if (count($missing) > 0) {
            throw new DatabaseConnectionException('LDAP configuration missing ' . implode(', ', $missing));
        }
        return true;
    }
1291547
public function connect(array $config)
    {
        $options = $this->getOptions($config);

        return $this->createConnection($this->getDsn($config), $config, $options);
    }
302578
protected function createSingleConnection(array $config)
    {
        $pdo = $this->createConnector($config)->connect($config);

        return $this->createConnection($config['driver'], $pdo, $config['database'], $config['prefix'], $config);
    }
226878
private function connect($config) {
		try {
			$this->pdoObject = new \PDO(
					$config["type"].':host=' . $config["serverName"] . ';dbname='
					. $config["dbName"] . ';port=' . $config["port"],
					$config["user"], $config["password"]);
			$this->pdoObject->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
			$this->pdoObject->exec("SET CHARACTER SET utf8");

		} catch (\PDOException $e) {
			print "Error!: " . $e->getMessage() . "<br/>";
		}
	}