1. 程式人生 > >封裝:PDO與MySQL之間的無縫切換

封裝:PDO與MySQL之間的無縫切換

params argument isset 釋放 結果 pdo ror exe tco

以下的例子是將MySQL和PDO封裝好,再無縫切換:

文件目錄:

技術分享

config.php文件:

<?php

return array(
    // 數據庫配置
    ‘DB‘ => array(
        ‘default_extension‘=>‘mysql‘, //這裏可以是pdo或mysql
    ),
    // 分頁配置
    // 上傳配置
    // 圖像處理配置
);

I_DB.interface.php文件:

<?php
/**
 * 數據庫接口
 */
interface I_DB {
    
public static function getInstance($config);// 獲取單例對象 public function my_query($sql); //執行增刪改 public function fetchAll($sql); //查詢所有 public function fetchRow($sql); //查詢一行 public function fetchColumn($sql); //查詢一個單行單列的一個值 }

MySQLDB.class.php文件:

<?php
header(‘content-type:text/html;charset=utf-8‘);
/** * MySQL數據庫工具類 */ //加載接口 include ‘./I_DB.interface.php‘; class MySQLDB implements I_DB{ private $host; //主機地址 private $port; //端口號 private $user; //用戶名 private $pass; //密碼 private $dbname; //數據庫名 private $charset;//字符集 private $link; //保存連接數據庫資源 private
static $instance = null; //單例模式中的$MySQLDB對象 /** *@param array $config 配置文件 */ private function __construct ($config) { // 初始化屬性的值 $this->init($config); // 連接數據庫 $this->my_connect(); // 設置字符集 $this->my_charset(); // 選擇數據庫 $this->my_dbname(); } /** * 只能new一次,單例模式 *@param array $config 傳遞給構造方法的數組參數 */ public static function getInstance($config) { if (self::$instance == null) { self::$instance = new self($config); } return self::$instance; } /*** *私有化克隆魔術方法 */ private function _clone() {} /** *初始化 *@param array $config 傳遞給初始化方法的數組參數 */ private function init($config) { $this->host = isset($config[‘host‘])?$config[‘host‘]:‘localhost‘; $this->port = isset($config[‘port‘])?$config[‘port‘]:‘3306‘; $this->user = isset($config[‘user‘])?$config[‘user‘]:‘root‘; $this->pass = isset($config[‘pass‘])?$config[‘pass‘]:‘‘; $this->dbname = isset($config[‘dbname‘])?$config[‘dbname‘]:‘‘; $this->charset = isset($config[‘charset‘])?$config[‘charset‘]:‘utf8‘; } /** *錯誤測試方法 *@param string $sql sql語句 *直接用途:用來增刪改 */ public function my_query($sql) { if ($result = mysql_query($sql)) { return $result; }else { echo "執行sql語句失敗;<br/>"; echo "錯誤代碼:",mysql_errno(),"<br/>"; echo "錯誤信息:",mysql_error(),‘<br/>‘; return false; } } /** *連接數據庫 */ private function my_connect() { if ($link = mysql_connect("$this->host:$this->port",$this->user,$this->pass)) { $this->link = $link; }else { echo "連接數據庫失敗:<br/>"; echo "錯誤代碼:",mysql_errno(),"<br/>"; echo "錯誤信息:",mysql_error(),‘<br/>‘; return false; } } /** *設置字符集 */ private function my_charset() { $sql = "set names $this->charset"; $this->my_query($sql); } /** *選擇數據庫 */ private function my_dbname() { $sql = "use $this->dbname"; return $this->my_query($sql); } /** *返回多行多列的結果集,二維數組 *@param string sql語句 *@return mixed(array|false) *執行成功返回數組,失敗返回false */ public function fetchAll($sql) { if($result = $this->my_query($sql)) { //返回資源結果集,遍歷 $rows[] = ‘‘; while ($row = mysql_fetch_assoc($result)) { $rows[] = $row; } //結果集使用完畢,主動釋放 mysql_free_result($result); //返回二維數組 return $rows; } else { return false; } } /** * 返回一行多列的結果集,一維數組 *@param string 一條sql語句 *@return mixed(array|false) 執行成功返回數組,失敗返回false */ public function fetchRow($sql) { if($result = $this->my_query($sql)) { //返回資源結果集,遍歷 $row = mysql_fetch_assoc($result); //結果集使用完畢,主動釋放 mysql_free_result($result); //返回一維數組 return $row; } else { return false; } } /** *返回一行一列的結果集,單一值 *@param string 一條sql語句 *@return mixed(array|false) 執行成功返回數組,失敗返回false */ public function fetchColumn($sql) { if($result = $this->my_query($sql)) { //返回資源結果集,提取 $row = mysql_fetch_row($result); //結果集使用完畢,主動釋放 mysql_free_result($result); //返回單一值 return isset($row[0])?$row[0]:false; } else { return false; } } /** *析構方法 */ public function __destruct() { @mysql_close($this->link); } /** *__sleep 序列化對象的時候觸發執行 */ public function __sleep() { return array(‘host‘,‘port‘,‘user‘,‘pass‘,‘charset‘,‘dbname‘) ; } /** *__wakeup 反序列化的時候觸發執行 *初始化操作 */ public function __wakeup() { //初始化操作 // 連接數據庫 $this->my_connect(); // 設置字符集 $this->my_charset(); // 選擇數據庫 $this->my_dbname(); } /** *__set 為一個不可訪問的屬性賦值的時候自動觸發 *@param string $name 屬性名 *@param mixed $value 屬性值 */ public function __set($name,$value) { $allow_set = array(‘host‘,‘port‘,‘user‘,‘pass‘,‘dbname‘,‘charset‘); if(in_array($name,$allow_set)) { //當前屬性可以被賦值 $this->$name = $value; } } /** *__get *獲得一個不可訪問的屬性的值的時候自動觸發 *@param string $name 屬性名 */ public function __get($name) { $allow_get = array(‘host‘,‘port‘,‘user‘,‘pass‘,‘dbname‘,‘charset‘); if (in_array($name,$allow_get)) { return $this->$name; } } /** *__call 訪問一個不可訪問的對象方法的時候觸發 *@param string $name *@param array $argument 參數列表 */ public function __call($name, $argument) { echo "對不起,您訪問的".$name."()方法不存在!<br/>"; } /** *__callstatic 訪問一個不可訪問的類方法(靜態方法)的時候觸發 *@param string $name *@param array $argument 參數列表 */ public static function __callStatic($name, $argument) { echo "對不起,您訪問的".$name."()靜態方法不存在!<br/>"; } }

PDODB.class.php文件:

<?php
header(‘content-type:text/html;charset=utf-8‘);
/**
 * 封裝PDODB類
 */
// 加載接口
include ‘./I_DB.interface.php‘;
class PDODB implements I_DB {
    /**
     * 定義相關屬性
     */
    private $host;   //主機地址
    private $port;     //端口號
    private $user;     //用戶名
    private $pass;     //密碼
    private $dbname; //數據庫名
    private $charset;//字符集
    private $dsn;      //數據源名稱
    private $pdo;    //用於存放PDO的一個對象
    // 靜態私有屬性用於保存單例對象
    private static $instance;    

    /**
     * [__construct 構造方法]
     * @param [array] $config [配置數組]
     */
    private function __construct($config) {
        // 初始化屬性
        $this->initParams($config);
        // 初始化dsn
        $this->initDSN();
        // 實例化PDO對象
        $this->initPDO();
        // 初始化PDO對象的屬性
        $this->initAttribute();
    }

    /**
     * [getInstance 獲取PDO單例對象的公開方法]
     * @param  [array] $config [description]
     * @return [PDOobject] self::$instance [pdo對象]
     */
    public static function getInstance($config) {
        if (!self::$instance instanceof self) {
            self::$instance = new self($config);
        }
        return self::$instance;
    }

    /**
     * [initParams 初始化屬性]
     * @param  [array] $config [配置數組]
     */
    private function initParams($config) {
        $this->host = isset($config[‘host‘])?$config[‘host‘]:‘localhost‘;
        $this->port = isset($config[‘port‘])?$config[‘port‘]:‘3306‘;
        $this->user = isset($config[‘user‘])?$config[‘user‘]:‘root‘;
        $this->pass = isset($config[‘pass‘])?$config[‘pass‘]:‘‘;
        $this->dbname = isset($config[‘dbname‘])?$config[‘dbname‘]:‘‘;
        $this->charset = isset($config[‘charset‘])?$config[‘charset‘]:‘utf8‘;
    }
    /**
     * [initDSN 初始化dsn]
     */
    private function initDSN() {
        $this->dsn = "mysql:host=$this->host;port=$this->port;dbname=$this->dbname;charset=$this->charset";
    }

    /**
     * [initPDO 實例化PDO對象]
     * @return [boolean] [false|none]
     */
    private function initPDO() {
        // 在實例化PDO對象的時候自動的走異常模式(也是唯一走異常模式的地方)
        try{
            $this->pdo = new PDO($this->dsn,$this->user,$this->pass);
        }catch(PDOException $e) {
            $this->my_error($e);
        }
    }

    /**
     * [initAttribute 初始化PDO對象屬性]
     * @return [boolean] [false|none]
     */
    private function initAttribute() {
        // 修改錯誤模式為異常模式
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
    }

    /**
     * [my_error 輸出異常信息]
     * @param  [PDOException] $e [異常對象]
     * @return [boolean]    [false|none]
     */
    private function my_error($e) {
        echo "執行sql語句失敗!<br/>";
        echo "錯誤的代碼是:",$e->getCode(),"<br/>";
        echo "錯誤的信息是:",$e->getMessage(),"<br/>";
        echo "錯誤的腳本是:",$e->getFile(),"<br/>";
        echo "錯誤的行號是:",$e->getLine(),‘<br/>‘;
        return false;
    }

    /**
     * [my_query 執行一條sql語句,實現增刪改]
     * @param  [string] $sql [sql語句]
     * @return [array] $result [資源結果集]
     */
    public function my_query($sql) {
        // 其實就是調用pdo對象中的exec方法
        try{
            $result = $this->pdo->exec($sql);
        }catch(PDOException $e) {
            $this->my_error($e);
        }
        return $result;
    }    

    /**
     * [fetchAll 查詢所有]
     * @param  [string] $sql [sql語句]
     * @return [arry] $result [資源結果集]
     */
    public function fetchAll($sql) {
        // 其實就是調用PDOStatment對象裏面的fetchAll方法
        try{
            $stmt = $this->pdo->query($sql);
            $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
            // 關閉遊標,釋放結果集
            $stmt->closeCursor();
        }catch(PDOException $e) {
            $this->my_error($e);
        }
        return $result;
    }

    /**
     * [fetchRow 查詢一條]
     * @param  [string] $sql [sql語句]
     * @return [arry] $result [資源結果集]
     */
    public function fetchRow($sql) {
        // 其實就是調用PDOStatment對象裏面的fetch方法
        try{
            $stmt = $this->pdo->query($sql);
            $result = $stmt->fetch(PDO::FETCH_ASSOC);
            // 關閉遊標,釋放結果集
            $stmt->closeCursor();
        }catch(PDOException $e) {
            $this->my_error($e);
        }
        return $result;
    }

    /**
     * [fetchColumn 查詢單行單列]
     * @param  [string] $sql [sql語句]
     * @return [arry] $result [資源結果集]
     */
    public function fetchColumn($sql) {
        // 其實就是調用PDOStatment對象裏面的fetchColumn方法
        try{
            $stmt = $this->pdo->query($sql);
            $result = $stmt->fetchColumn();
            // 關閉遊標,釋放結果集
            $stmt->closeCursor();
        }catch(PDOException $e) {
            $this->my_error($e);
        }
        return $result;
    }


    /**
     * [__clone 私有化克隆方法,保護單例模式]
     */
    private function __clone() {}


    /**
     * [__set 為一個不可訪問的屬性賦值的時候自動觸發]
     * @param [string] $name  [屬性名]
     * @param [mixed] $value [屬性值]
     */
     public function __set($name,$value) {
         $allow_set = array(‘host‘,‘port‘,‘user‘,‘pass‘,‘dbname‘,‘charset‘);
         if(in_array($name,$allow_set)) {
             //當前屬性可以被賦值
             $this->$name = $value;
         }
     }


    /**
     * [__get *獲得一個不可訪問的屬性的值的時候自動觸發]
     * @param  [string] $name [屬性名]
     * @return [string] $name的value [該屬性名的值]
     */
     public function __get($name) {
         $allow_get = array(‘host‘,‘port‘,‘user‘,‘pass‘,‘dbname‘,‘charset‘);
         if (in_array($name,$allow_get)) {
             return $this->$name;
         }
     }


    /**
     * [__call 訪問一個不可訪問的對象方法的時候觸發]
     * @param  [string] $name     [屬性名]
     * @param  [array] $argument [參數列表]
     */
     public function __call($name, $argument) {
         echo "對不起,您訪問的".$name."()方法不存在!<br/>";
     }
    
    /**
     * [__callstatic 訪問一個不可訪問的類方法(靜態方法)的時候觸發]
     * @param  [string] $name     [屬性名]
     * @param  [array] $argument [參數列表]
     */
     public static function __callStatic($name, $argument) {
         echo "對不起,您訪問的".$name."()靜態方法不存在!<br/>";
     }
}

最後的測試類:

<?php
header(‘content-type:text/html;charset=utf-8‘);
// 先讀取配置文件
$conf = include ‘./config.php‘;

$config = [
    ‘pass‘=>‘123456‘,
    ‘dbname‘=>‘bbs‘
];

// 實例化數據庫操作對象
switch ($conf[‘DB‘][‘default_extension‘]) {
    case ‘mysql‘:
        include ‘./MySQLDB.class.php‘;
        $db = MySQLDB::getInstance($config);
        break;
    case ‘pdo‘:
        include ‘./PDODB.class.php‘;
        $db = PDODB::getInstance($config);
        break;
    default:
        break;
}

$sql = "select * from user limit 4";
echo "<pre>";
var_dump($db->fetchAll($sql));
echo "</pre>";
echo "<hr>";

測試結果:

技術分享

還可以在配置文件config.php中切換到pdo中操作數據庫!

封裝:PDO與MySQL之間的無縫切換