Db.class.php 5.55 KB
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2014 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace Think;

/**
 * ThinkPHP 数据库中间层实现类
 */
class Db
{

    private static $instance = array(); // 数据库连接实例

    private static $_instance = null; // 当前数据库连接实例

    /**
     * 取得数据库类实例
     * 
     * @static
     *
     * @access public
     * @param mixed $config
     *            连接配置
     * @return Object 返回数据库驱动类
     */
    static public function getInstance($config = array())
    {
        $md5 = md5(serialize($config));
        if (! isset(self::$instance[$md5])) {
            // 解析连接参数 支持数组和字符串
            $options = self::parseConfig($config);
            // 兼容mysqli
            if ('mysqli' == $options['type']) {
                $options['type'] = 'mysql';
            }
            // 如果采用lite方式 仅支持原生SQL 包括query和execute方法
            $class = $options['lite'] ? 'Think\Db\Lite' : 'Think\\Db\\Driver\\' . ucwords(strtolower($options['type']));
            if (class_exists($class)) {
                self::$instance[$md5] = new $class($options);
            } else {
                // 类没有定义
                E(L('_NO_DB_DRIVER_') . ': ' . $class);
            }
        }
        self::$_instance = self::$instance[$md5];
        
        return self::$_instance;
    }

    /**
     * 数据库连接参数解析
     * 
     * @static
     *
     * @access private
     * @param mixed $config            
     * @return array
     */
    static private function parseConfig($config)
    {
        if (! empty($config)) {
            if (is_string($config)) {
                return self::parseDsn($config);
            }
            $config = array_change_key_case($config);
            $config = array(
                'type' => $config['db_type'],
                'username' => $config['db_user'],
                'password' => $config['db_pwd'],
                'hostname' => $config['db_host'],
                'hostport' => $config['db_port'],
                'database' => $config['db_name'],
                'dsn' => isset($config['db_dsn']) ? $config['db_dsn'] : null,
                'params' => isset($config['db_params']) ? $config['db_params'] : null,
                'charset' => isset($config['db_charset']) ? $config['db_charset'] : 'utf8',
                'deploy' => isset($config['db_deploy_type']) ? $config['db_deploy_type'] : 0,
                'rw_separate' => isset($config['db_rw_separate']) ? $config['db_rw_separate'] : false,
                'master_num' => isset($config['db_master_num']) ? $config['db_master_num'] : 1,
                'slave_no' => isset($config['db_slave_no']) ? $config['db_slave_no'] : '',
                'debug' => isset($config['db_debug']) ? $config['db_debug'] : APP_DEBUG,
                'lite' => isset($config['db_lite']) ? $config['db_lite'] : false
            );
        } else {
            $config = array(
                'type' => C('DB_TYPE'),
                'username' => C('DB_USER'),
                'password' => C('DB_PWD'),
                'hostname' => C('DB_HOST'),
                'hostport' => C('DB_PORT'),
                'database' => C('DB_NAME'),
                'dsn' => C('DB_DSN'),
                'params' => C('DB_PARAMS'),
                'charset' => C('DB_CHARSET'),
                'deploy' => C('DB_DEPLOY_TYPE'),
                'rw_separate' => C('DB_RW_SEPARATE'),
                'master_num' => C('DB_MASTER_NUM'),
                'slave_no' => C('DB_SLAVE_NO'),
                'debug' => C('DB_DEBUG', null, APP_DEBUG),
                'lite' => C('DB_LITE')
            );
        }
        
        return $config;
    }

    /**
     * DSN解析
     * 格式: mysql://username:passwd@localhost:3306/DbName?param1=val1&param2=val2#utf8
     * 
     * @static
     *
     * @access private
     * @param string $dsnStr            
     * @return array
     */
    static private function parseDsn($dsnStr)
    {
        if (empty($dsnStr)) {
            return false;
        }
        $info = parse_url($dsnStr);
        if (! $info) {
            return false;
        }
        $dsn = array(
            'type' => $info['scheme'],
            'username' => isset($info['user']) ? $info['user'] : '',
            'password' => isset($info['pass']) ? $info['pass'] : '',
            'hostname' => isset($info['host']) ? $info['host'] : '',
            'hostport' => isset($info['port']) ? $info['port'] : '',
            'database' => isset($info['path']) ? substr($info['path'], 1) : '',
            'charset' => isset($info['fragment']) ? $info['fragment'] : 'utf8'
        );
        if (isset($info['query'])) {
            parse_str($info['query'], $dsn['params']);
        } else {
            $dsn['params'] = array();
        }
        
        return $dsn;
    }
    
    // 调用驱动类的方法
    static public function __callStatic($method, $params)
    {
        return call_user_func_array(array(
            self::$_instance,
            $method
        ), $params);
    }
}