簡單的使用 PDO 操作 MySQL 數據庫類

<?php
/**
 * 簡單的使用 PDO 操作 MySQL 數據庫類
 * 類爲靜態類,全部靜態調用
 */
class Mysql
{
    private static $conn;

    public static function getInstance () {
        if (!self::$conn) {
            $mysql = Conf::getMysql();
            $_host = $mysql['host'];
            $_port = $mysql['port'];
            $_user = $mysql['user'];
            $_pass = $mysql['pass'];
            $_char = $mysql['char'];
            $_db = $mysql['db'];
            $dsn = "mysql:host=$_host;dbname=$_db;charset=$_char";

            try {
                self::$conn = new PDO($dsn, $_user, $_pass);
            } catch (PDOException $e) {
                throw new Exception(Constants::E_CONNECT_TO_DB . ': '. $e->getMessage());
            }
        }

        return self::$conn;
    }

    /**
     * 插入數據到數據庫
     * @param string $tableName 數據庫名
     * @param array  $data      要插入的數據
     */
    public static function insert ($tableName, $data) {
        if (gettype($tableName) !== 'string' || gettype($data) !== 'array') {
            throw new Exception(Constants::E_CALL_FUNCTION_PARAM);
        }

        $prepareData = self::prepare($data);
        $prepareFieldsStr = implode(', ', array_keys($prepareData));
        $fieldsStr = implode(', ', array_keys($data));
        $sql = "INSERT INTO `$tableName` ($fieldsStr) VALUES ($prepareFieldsStr)";

        // 執行 SQL 語句
        $query = self::raw($sql, $prepareData);
        return $query->rowCount();
    }

    /**
     * 查詢多行數據
     * @param string        $tableName 數據庫名
     * @param array         $columns   查詢的列名數組
     * @param array|string  $condition 查詢條件,若爲字符串則會被直接拼接進 SQL 語句中,支持鍵值數組
     * @param string        $operator  condition 連接的操作符:and|or
     * @param string        $suffix    SQL 查詢後綴,例如 order, limit 等其他操作
     * @return array
     */
    public static function select ($tableName, $columns = ['*'], $conditions = '', $operator = 'and', $suffix = '') {
        if (   gettype($tableName)  !== 'string'
            || (gettype($conditions)!== 'array' && gettype($conditions) !== 'string')
            || gettype($columns)    !== 'array'
            || gettype($operator)   !== 'string'
            || gettype($suffix)     !== 'string') {
            throw new Exception(Constants::E_CALL_FUNCTION_PARAM);
        }

        list($condition, $execValues) = array_values(self::conditionProcess($conditions, $operator));

        $column = implode(', ', $columns);
        // 拼接 SQL 語句
        $sql = "SELECT $column FROM `$tableName`";

        // 如果有條件則拼接 WHERE 關鍵則
        if ($condition) {
            $sql .= " WHERE $condition";
        }

        // 拼接後綴
        $sql .= " $suffix";

        // 執行 SQL 語句
        $query = self::raw($sql, $execValues);
        $allResult = $query->fetchAll(PDO::FETCH_OBJ);
        return $allResult === NULL ? [] : $allResult;
    }

    /**
     * 查詢單行數據
     * @param string        $tableName 數據庫名
     * @param array         $columns   查詢的列名數組
     * @param array|string  $condition 查詢條件,若爲字符串則會被直接拼接進 SQL 語句中,支持鍵值數組
     * @param string        $operator  condition 連接的操作符:and|or
     * @param string        $suffix    SQL 查詢後綴,例如 order, limit 等其他操作
     * @return object
     */
    public static function row ($tableName, $columns = ['*'], $conditions = '', $operator = 'and', $suffix = '') {
        $rows = self::select($tableName, $columns, $conditions, $operator, $suffix);
        return count($rows) === 0 ? NULL : $rows[0];
    }

    /**
     * 更新數據庫
     * @param string        $tableName 數據庫名
     * @param array         $updates   更新的數據對象
     * @param array|string  $condition 查詢條件,若爲字符串則會被直接拼接進 SQL 語句中,支持鍵值數組
     * @param string        $operator  condition 連接的操作符:and|or
     * @param string        $suffix    SQL 查詢後綴,例如 order, limit 等其他操作
     * @return number 受影響的行數
     */
    public static function update ($tableName, $updates, $conditions = '', $operator = 'and', $suffix = '') {
        if (   gettype($tableName)  !== 'string'
            || gettype($updates)    !== 'array'
            || (gettype($conditions)!== 'array' && gettype($conditions) !== 'string')
            || gettype($operator)   !== 'string'
            || gettype($suffix)     !== 'string') {
            throw new Exception(Constants::E_CALL_FUNCTION_PARAM);
        }

        // 處理要更新的數據
        list($processedUpdates, $execUpdateValues) = array_values(self::conditionProcess($updates, ','));

        // 處理條件
        list($condition, $execValues) = array_values(self::conditionProcess($conditions, $operator));

        // 拼接 SQL 語句
        $sql = "UPDATE `$tableName` SET $processedUpdates";
        
        // 如果有條件則拼接 WHERE 關鍵則
        if ($condition) {
            $sql .= " WHERE $condition";
        }

        // 拼接後綴
        $sql .= " $suffix";

        // 執行 SQL 語句
        $query = self::raw($sql, array_merge($execUpdateValues, $execValues));
        return $query->rowCount();
    }

    /**
     * 刪除數據
     * @param string        $tableName 數據庫名
     * @param array|string  $condition 查詢條件,若爲字符串則會被直接拼接進 SQL 語句中,支持鍵值數組
     * @param string        $operator  condition 連接的操作符:and|or
     * @param string        $suffix    SQL 查詢後綴,例如 order, limit 等其他操作
     * @return number 受影響的行數
     */
    public static function delete ($tableName, $conditions, $operator = 'and', $suffix = '') {
        if (   gettype($tableName)  !== 'string'
            || ($conditions && gettype($conditions)!== 'array' && gettype($conditions) !== 'string') 
            || gettype($operator)   !== 'string'
            || gettype($suffix)     !== 'string') {
            throw new Exception(Constants::E_CALL_FUNCTION_PARAM);
        }

        // 處理條件
        list($condition, $execValues) = array_values(self::conditionProcess($conditions, $operator));

        // 拼接 SQL 語句
        $sql = "DELETE FROM `$tableName` WHERE $condition $suffix";

        // 執行 SQL 語句
        $query = self::raw($sql, $execValues);
        return $query->rowCount();
    }

    /**
     * 執行原生 SQL 語句
     * @param string $sql  要執行的 SQL 語句
     * @param array  $data SQL 語句的參數值
     */
    public static function raw ($sql, $execValues = []) {
        $query = self::getInstance()->prepare($sql);
        $result = $query->execute($execValues);
        
        if ($result) {
            return $query;
        } else {
            $error = $query->errorInfo();
            throw new Exception(Constants::E_EXEC_SQL_QUERY . ': ' . $error[2]);
        }
    }

    /**
     * 按照指定的規則處理條件數組
     * @example ['a' => 1, 'b' => 2] 會被轉換爲 ['a = :a and b = :b', [':a' => 1, ':b' => 2]]
     * @param array|string $conditions 條件數組或字符串
     * @param string       $operator  condition 連接的操作符:and|or
     */
    private static function conditionProcess ($conditions, $operator = 'and') {
        $condition = '';
        $execValues = [];
        if (gettype($conditions) === 'array') {
            $cdt = [];

            foreach ($conditions as $key => $value) {
                if (gettype($value) === 'number') {
                    array_push($cdt, $value);
                } else {
                    array_push($cdt, $key . ' = :' . $key);
                    $execValues[$key] = $value;
                }
            }

            $condition = implode(' ' . $operator . ' ', $cdt);
        } else {
            $condition = $conditions;
        }

        return [
            $condition,
            self::prepare($execValues)
        ];
    }

    /**
     * 轉換數據爲 PDO 支持的 prepare 過的數據
     * @example ['a' => 1] 會被轉換爲 [':a' => 1]
     * @param array $dataArray 要轉換的數據
     */
    private static function prepare ($dataArray) {
        $prepareData = [];
        
        foreach ($dataArray as $field => $value) {
            $prepareData[':' . $field] = $value;
        }

        return $prepareData;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章