<?php
/*
* Author: AthrunSoft
* class.pdomysql.php 0.01 2012-4-15
*/
class pdomysql {
public static $dbtype = 'mysql';
public static $dbhost = '';
public static $dbport = '';
public static $dbname = '';
public static $dbuser = '';
public static $dbpass = '';
public static $charset = '';
public static $stmt = null;
public static $DB = null;
public static $connect = true; //是否長連接
public static $debug = false;
private static $parms = array();
/**
* 構造函數
*/
public function __construct() {
self::$dbtype = 'mysql';
self::$dbhost = DBHOST;
self::$dbport = DBPORT;
self::$dbname = DBNAME;
self::$dbuser = DBUSER;
self::$dbpass = DBPASS;
self::$connect = ISCONNECT;
self::$charset = CHARSET;
self::connect();
self::$DB->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
self::$DB->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
self::execute('SET NAMES ' . self::$charset);
}
/**
*析構函數
*/
public function __destruct() {
self::close();
}
/*********************基本方法開始*********************/
/**
* 作用:連結資料庫
*/
public function connect() {
try {
self::$DB = new PDO(self::$dbtype . ':host=' . self::$dbhost . ';port=' . self::
$dbport . ';dbname=' . self::$dbname, self::$dbuser, self::$dbpass, array(PDO::
ATTR_PERSISTENT => self::$connect));
}
catch (PDOException $e) {
die("Connect Error Infomation:" . $e->getMessage());
}
}
/**
*關閉資料連接
*/
public function close() {
self::$DB = null;
}
/**
* 對字串進行轉義
*/
public function quote($str) {
return self::$DB->quote($str);
}
/**
* 返回一個日期時間字符
*/
public function now() {
return date("Y-m-d H:i:s");
}
/**
* 作用:獲取當前庫的所有表名
* 返回:當前庫的所有表名
* 類型:陣列
*/
public function getTablesName() {
self::$stmt = self::$DB->query('SHOW TABLES FROM ' . self::$dbname);
$result = self::$stmt->fetchAll(PDO::FETCH_NUM);
self::$stmt = null;
return $result;
}
/**
* 作用:獲取資料表裡的欄位
* 返回:表字段結構
* 類型:陣列
*/
public function getFields($table) {
self::$stmt = self::$DB->query("DESCRIBE $table");
$result = self::$stmt->fetchAll(PDO::FETCH_ASSOC);
self::$stmt = null;
return $result;
}
/**
* 作用:獲得最後INSERT的主鍵ID
* 返回:最後INSERT的主鍵ID
* 類型:數字
*/
public function getLastId() {
return self::$DB->lastInsertId();
}
/**
*事務開始
*/
public function autocommit() {
self::$DB->beginTransaction();
}
/**
*事務提交
*/
public function commit() {
self::$DB->commit();
}
/**
*交易復原
*/
public function rollback() {
self::$DB->rollback();
}
/**
* 作用:執行INSERT\UPDATE\DELETE
* 返回:執行語句影響行數
* 類型:數字
*/
public function execute($sql) {
self::getPDOError($sql);
return self::$DB->exec($sql);
}
/**
* 獲取要操作的資料
* 返回:合併後的SQL語句
* 類型:字串
*/
private function getCode($table, $args) {
$code = '';
if (is_array($args)) {
foreach ($args as $k => $v) {
if ($v == '') {
continue;
}
$code .= "`$k`='$v',";
}
}
$code = substr($code, 0, -1);
return $code;
}
/**
* 執行具體SQL操作
* 返回:運行結果
* 類型:陣列或數位
*/
private function _fetch($sql, $type) {
$result = array();
self::$stmt = self::$DB->query($sql);
self::getPDOError($sql);
self::$stmt->setFetchMode(PDO::FETCH_ASSOC);
switch ($type) {
case '0':
$result = self::$stmt->fetch();
break;
case '1':
$result = self::$stmt->fetchAll();
break;
case '2':
if ($sql) {
$result = self::$stmt->fetchColumn();
} elseif (self::$stmt) {
$result = self::$stmt->rowCount();
} else {
$result = 0;
}
break;
}
self::$stmt = null;
return $result;
}
/**
* 分頁計算
*/
private function count($pagesize, &$page, &$pagecount, &$recordcount) {
//獲取記錄行數,計算頁數,以及重新檢查當前頁碼
$pagecount = ceil($recordcount / $pagesize);
if ($pagecount > 0) {
if ($page > $pagecount) {
$page = $pagecount;
} elseif ($page < 1) {
$page = 1;
}
} else {
$page = 1;
}
}
/*********************基本方法結束*********************/
/*********************Sql操作方法開始*********************/
/**
* 作用:插入資料
* 返回:表內記錄
* 類型:陣列
* 參數:$db->insert('$table',array('title'=>'Zxsv'))
*/
public function add($table, $args) {
$sql = "INSERT INTO `$table` SET ";
$code = self::getCode($table, $args);
$sql .= $code;
return self::execute($sql);
}
/**
* 修改資料
* 返回:記錄數
* 類型:數字
* 參數:$db->update($table,array('title'=>'Zxsv'),array('id'=>'1'),$where ='id=3');
*/
public function update($table, $args, $where) {
$code = self::getCode($table, $args);
$sql = "UPDATE `$table` SET ";
$sql .= $code;
$sql .= " Where $where";
return self::execute($sql);
}
/**
* 作用:刪除資料
* 返回:表內記錄
* 類型:陣列
* 參數:$db->delete($table,$condition = null,$where ='id=3')
*/
public function delete($table, $where) {
$sql = "DELETE FROM `$table` Where $where";
return self::execute($sql);
}
/**
* 作用:獲取單行資料
* 返回:表內第一條記錄
* 類型:陣列
* 參數:$db->fetOne($table,$condition = null,$field = '*',$where ='')
*/
public function fetOne($table, $field = '*', $where = false) {
$sql = "SELECT {$field} FROM `{$table}`";
$sql .= ($where) ? " WHERE $where" : '';
return self::_fetch($sql, $type = '0');
}
/**
* 作用:獲取單行資料
* 返回:表內第一條記錄
* 類型:陣列
* 參數:select * from table where id='1'
*/
public function getOne($sql) {
return self::_fetch($sql, $type = '0');
}
/**
* 作用:獲取首行首列資料
* 返回:首行首列欄位值
* 類型:值
* 參數:select `a` from table where id='1'
*/
public function scalar($sql, $fieldname) {
$row = self::_fetch($sql, $type = '0');
return $row[$fieldname];
}
/**
* 獲取記錄總數
* 返回:記錄數
* 類型:數字
* 參數:$db->fetRow('$table',$condition = '',$where ='');
*/
public function fetRowCount($table, $field = '*', $where = false) {
$sql = "SELECT COUNT({$field}) AS num FROM `$table`";
$sql .= ($where) ? " WHERE $where" : '';
return self::_fetch($sql, $type = '2');
}
/**
* 獲取記錄總數
* 返回:記錄數
* 類型:數字
* 參數:select count(*) from table
*/
public function getRowCount($sql) {
return self::_fetch($sql, $type = '2');
}
/**
* 作用:獲取所有資料
* 返回:表內記錄
* 類型:二維陣列
* 參數:$db->fetAll('$table',$condition = '',$field = '*',$orderby = '',$limit = '',$where='')
*/
public function fetAll($table, $field = '*', $orderby = false, $where = false) {
$sql = "SELECT {$field} FROM `{$table}`";
$sql .= ($where) ? " WHERE $where" : '';
$sql .= ($orderby) ? " ORDER BY $orderby" : '';
return self::_fetch($sql, $type = '1');
}
/**
* 作用:獲取分頁資料
* 返回:表內記錄
* 類型:二維陣列
*/
public function fetPageAll($table, $field = '*', $where = false, $orderby = false,
$pagesize, &$page, &$pagecount, &$recordcount) {
$sql = "SELECT {$field} FROM `{$table}`";
$sql .= ($where) ? " WHERE $where" : '';
return self::getPageAll($sql, $orderby, $pagesize, $page, $pagecount, $recordcount);
}
/**
* 作用:獲取所有資料
* 返回:表內記錄
* 類型:二維陣列
* 參數:select * from table
*/
public function getAll($sql) {
return self::_fetch($sql, $type = '1');
}
/**
* 作用:獲取分頁資料
* 返回:表內記錄
* 類型:二維陣列
*/
public function getPageAll($sql, $orderby = false, $pagesize, &$page, &$pagecount,
&$recordcount) {
$sqlcount = "select count(1) as `recordcount` from ($sql) as t;";
$recordcount = self::scalar($sqlcount, 'recordcount');
self::count($pagesize, $page, $pagecount, $recordcount);
$start = ($page - 1) * $pagesize;
$sql .= ($orderby) ? " ORDER BY $orderby" : '';
$sql .= " limit $start,$pagesize";
return self::_fetch($sql, $type = '1');
}
/*********************Sql操作方法結束*********************/
/*********************Pram操作方法開始*********************/
/**
* 作用:獲取單行資料
* 返回:表內第一條記錄
* 類型:陣列
*/
public function pramGetOne($sql, $input_parameters) {
return self::_pramfetch($sql, $input_parameters, $type = '0');
}
/**
* 作用:獲取所有資料
* 返回:表內記錄
* 類型:二維陣列
*/
public function pramGetAll($sql, $input_parameters) {
return self::_pramfetch($sql, $input_parameters, $type = '1');
}
/**
* 作用:執行帶參數SQL操作
* 返回:執行語句影響行數
* 類型:數字
*/
public function pramExecute($sql, $input_parameters) {
return self::_pramfetch($sql, $input_parameters, $type = '2');
}
/**
* 作用:獲取首行首列資料
* 返回:首行首列欄位值
* 類型:值
*/
public function pramScalar($sql, $input_parameters, $fieldname) {
$row = self::_pramfetch($sql, $input_parameters, $type = '0');
return $row[$fieldname];
}
/**
* 執行帶參數SQL操作
* 返回:運行結果
* 類型:陣列或數位
*/
private function _pramfetch($sql, $input_parameters, $type) {
$result = array();
self::$stmt = self::$DB->prepare($sql);
self::getPDOError($sql);
self::$stmt->execute($input_parameters);
self::getSTMTError($sql);
self::$stmt->setFetchMode(PDO::FETCH_ASSOC);
switch ($type) {
case '0':
$result = self::$stmt->fetch();
break;
case '1':
$result = self::$stmt->fetchAll();
break;
case '2':
if (self::$stmt) {
$result = self::$stmt->rowCount();
} else {
$result = 0;
}
break;
}
self::$stmt = null;
return $result;
}
/*********************Pram操作方法結束*********************/
/*********************Proc操作方法開始*********************/
/**
* 添加參數
*/
public function pramadd($parameter, $variable, $data_type, $length) {
array_push(self::$parms, array($parameter, $variable, $data_type, $length));
}
/**
* 清除所有參數
*/
public function pramclear() {
self::$parms = array();
}
/**
* 作用:獲取單行資料
* 返回:表內第一條記錄
* 類型:陣列
*/
public function procGetOne($sql) {
return self::_procfetch($sql, $type = '0');
}
/**
* 作用:獲取所有資料
* 返回:表內記錄
* 類型:二維陣列
*/
public function procGetAll($sql) {
return self::_procfetch($sql, $type = '1');
}
/**
* 作用:執行一個存儲過程
* 返回:執行語句影響行數
* 類型:數字
*/
public function procExecute($sql) {
return self::_procfetch($sql, $type = '2');
}
/**
* 作用:獲取out型的return
*/
public function getReturn() {
return self::scalar("select @ireturn AS iReturn", "iReturn");
}
/**
* 執行帶參數SQL操作
* 返回:運行結果
* 類型:陣列或數位
*/
private function _procfetch($sql, $type) {
$result = array();
self::$stmt = self::$DB->prepare($sql);
self::getPDOError($sql);
foreach (self::$parms as $pram) {
self::$stmt->bindParam($pram[0], $pram[1], $pram[2], $pram[3]);
}
self::$stmt->execute();
self::getSTMTError($sql);
self::$stmt->setFetchMode(PDO::FETCH_ASSOC);
switch ($type) {
case '0':
$result = self::$stmt->fetch();
break;
case '1':
// do{
// $result[] = self::$stmt->fetchAll();
// } while (self::$stmt->nextRowset());
$result = self::$stmt->fetchAll();
self::$stmt->closeCursor();
break;
case '2':
if (self::$stmt) {
$result = self::$stmt->rowCount();
} else {
$result = 0;
}
break;
}
self::$stmt = null;
return $result;
}
/**
* 權為測試使用,目前沒有辦法獲取到OUT參數.
* 另外在一存講過程中若有rowset,同時還有OUT參數時,
* 即使$db->scalar("select @Rcount AS Rcount", "Rcount")這种方式仍然獲到不到,
* 執行時會出現下面的錯誤:
* Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
*/
public function procExecOut() {
//$colour = 'red';
self::$stmt = self::$DB->prepare('CALL puree_fruit(?)');
self::$stmt->bindParam(1, $colour,PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 4000);
self::$stmt->execute();
print("After pureeing fruit, the colour is: $colour");
}
/*********************Proc操作方法結束*********************/
/*********************錯誤處理開始*********************/
/**
* 設置是否為調試模式
*/
public function setDebugMode($mode = true) {
return ($mode == true) ? self::$debug = true : self::$debug = false;
}
/**
* 捕獲PDO錯誤資訊
* 返回:出錯資訊
* 類型:字串
*/
private function getPDOError($sql) {
self::$debug ? self::errorfile($sql) : '';
if (self::$DB->errorCode() != '00000') {
$info = (self::$stmt) ? self::$stmt->errorInfo() : self::$DB->errorInfo();
echo (self::sqlError('mySQL Query Error', $info[2], $sql));
exit();
}
}
private function getSTMTError($sql) {
self::$debug ? self::errorfile($sql) : '';
if (self::$stmt->errorCode() != '00000') {
$info = (self::$stmt) ? self::$stmt->errorInfo() : self::$DB->errorInfo();
echo (self::sqlError('mySQL Query Error', $info[2], $sql));
exit();
}
}
/**
* 寫入錯誤日志
*/
private function errorfile($sql) {
echo $sql . '<br />';
$errorfile = _ROOT . './dberrorlog.php';
$sql = str_replace(array("\n", "\r", "\t", " ", " ", " "), array(" ", " ",
" ", " ", " ", " "), $sql);
if (!file_exists($errorfile)) {
$fp = file_put_contents($errorfile, "<?PHP exit('Access Denied'); ?>\n" . $sql);
} else {
$fp = file_put_contents($errorfile, "\n" . $sql, FILE_APPEND);
}
}
/**
* 作用:運行錯誤資訊
* 返回:運行錯誤資訊和SQL語句
* 類型:字元
*/
private function sqlError($message = '', $info = '', $sql = '') {
$html = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml">';
$html .= '<head><title>mySQL Message</title><style type="text/css">body {margin:0px;color:#555555;font-size:12px;background-color:#efefef;font-family:Verdana} ol {margin:0px;padding:0px;} .w {800px;margin:100px auto;padding:0px;border:1px solid #cccccc;background-color:#ffffff;} .h {padding:8px;background-color:#ffffcc;} li {height:auto;padding:5px;line-height:22px;border-top:1px solid #efefef;list-style:none;overflow:hidden;}</style></head>';
$html .= '<body><div class="w"><ol>';
if ($message) {
$html .= '<div class="h">' . $message . '</div>';
}
$html .= '<li>Date: ' . date('Y-n-j H:i:s', time()) . '</li>';
if ($info) {
$html .= '<li>SQLID: ' . $info . '</li>';
}
if ($sql) {
$html .= '<li>Error: ' . $sql . '</li>';
}
$html .= '</ol></div></body></html>';
return $html;
}
/*********************錯誤處理結束*********************/
}
?>
此类还有两个问题没有处理(基本也可以使用):
1,在调用有out/inout参数的mysql存储过程时,没有办法像下面这样获取参数值,以下方法是官方的demo,可在我电脑上却从来没有获取到相应的值.
/* Call a stored procedure with an INOUT parameter */
$colour = 'red';
$sth = $dbh->prepare('CALL puree_fruit(?)');
$sth->bindParam(1, $colour, PDO::PARAM_STR|PDO::PARAM_INPUT_OUTPUT, 12);
$sth->execute();
print("After pureeing fruit, the colour is: $colour");
2,因为上面没有办法用PDO::PARAM_INPUT_OUTPUT的方式来获到out值.因此我改以下面的方式处理.结果又遇到另一个错误.好像是说没办法返回多个rowset的问题.
$db->pramclear();
$db->pramadd(1, 3, PDO::PARAM_INT,4,false);
$db->procGetAll("CALL UP_Banner_GetList(?,@Rcount);");
$db->scalar("select @Rcount AS Rcount", "Rcount");
错误信息:
Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
以上两个问题点在网上也找了很多资料,有的说是php的bug,也有的说在linux机器上不会有这样的问题.弄了这几天总的感觉是对pdo挺失望的.原以为自己可以封装好一个操作类,方便以后使用.希望哪位高手如果有也有此经历,请留言告之在下如何解决.谢谢!