程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> phpPDO連接mysql

phpPDO連接mysql

編輯:MySQL綜合教程

phpPDO連接mysql


最近在linux裝了新的環境,php5.6+mysql5.5+nginx。然後用原來的mysql鏈接數據庫出現的錯誤。

原因就是說連接數據庫的方法太舊。建議我用mysqli和PDO來連接數據庫。

好吧,咱也不能落後,使用mysqli的確也簡單了不少,但是PDO貌似更簡單。效率也會得到提升。根據官方文檔,貌似對於sql注入的一些風險也做了屏蔽。所以今天寫的 博客就是關於php用PDO連接mysql的一些介紹啦!

【PDO是啥】

PDO是PHP 5新加入的一個重大功能,因為在PHP 5以前的php4/php3都是一堆的數據庫擴展來跟各個數據庫的連接和處理,什麼php_mysql.dll、php_pgsql.dll、php_mssql.dll、php_sqlite.dll等等擴展來連接MySQL、PostgreSQL、MS SQL Server、SQLite,同樣的,我們必須借助 ADOdb、PEAR::DB、PHPlib::DB之類的數據庫抽象類來幫助我們,無比煩瑣和低效,畢竟,php代碼的效率怎麼能夠我們直接用C/C++寫的擴展效率高捏?所以嘛,PDO的出現是必然的,大家要平靜學習的心態去接受使用,也許你會發現能夠減少你不少功夫哦。

下面說說PDO基於php的版本:

PDO 是 PHP 5.1 發行的,也就是說,在 5.1 之前的版本是不支持 PDO,5.1之後的都支持啦。在PHP5.0的PECL擴展中也可以使用。

PDO如何使用:

這裡我們就以PHP的黃金搭檔mysql作為例子看看:

PDO_MYSQL:PDO_MYSQL是PDO接口能夠完成連接mysql數據庫的驅動(注:僅使用於mysql 3.x以上版本)。

安裝:打開php.ini文件,可以找到如下代碼,這裡可以看到mysql的驅動默認已經打開(前面沒有用於注釋的分號),如有連接其他數據庫的需要,自行添加其他數據庫的驅動程序(取出相應的項前面的分號,沒有的添上)。

    //各數據庫的PDO驅動  
    extension=php_pdo.dll   
    extension=php_pdo_firebird.dll //Firebird  
    extension=php_pdo_informix.dll //Informix  
    extension=php_pdo_mssql.dll    //sql server  
    extension=php_pdo_mysql.dll    //mysql  
    extension=php_pdo_oci.dll      //Oracle  
    extension=php_pdo_oci8.dll   
    extension=php_pdo_odbc.dll     //DB2  
    extension=php_pdo_pgsql.dll    //PostgreSQL  
    extension=php_pdo_sqlite.dll   //SQLite  
連接:通過創建PDO基類的實例創建連接。
    //連接到數據庫  
    $db = new PDO('mysql:host=localhost;dbname=test', $user, $pass);  

簡單的查詢方法:

<?php
header('content-type:text/html;charset=utf-8');
try {  
    $db = new PDO('mysql:host=127.0.0.1;dbname=test', 'root', '');  
    //查詢  
	$rows = $db->query('SELECT * from members')->fetchAll(PDO::FETCH_ASSOC);
	$rs = array();
    foreach($rows as $row) {  
        $rs[] = $row; 
    }  
    $db = null;  
} catch (PDOException $e) {  
    print "Error!: " . $e->getMessage() . "<br/>";  
    die();  
}
print_r($rs);
?>

不明白啥意思,俺們來慢慢講講。這行:
$dsn = "mysql:host=127.0.0.1;dbname=test";
就是構造我們的DSN(數據源),看看裡面的信息包括:數據庫類型是mysql,主機地址是localhost,數據庫名稱是test,就這麼幾個信息。不同數據庫的數據源構造方式是不一樣的。

$db = new PDO($dsn, 'root', '');
初始化一個PDO對象,構造函數的參數第一個就是我們的數據源,第二個是連接數據庫服務器的用戶,第三個參數是密碼。我們不能保證連接成功,後面我們會講到異常情況,這裡我們姑且認為它是連接成功的。

$count = $db->exec("INSERT INTO foo SET name = 'heiyeluren',gender='男',time=NOW()");
echo $count;
調用我們連接成功的PDO對象來執行一個查詢,這個查詢是一個插入一條記錄的操作,使用PDO::exec() 方法會返回一個影響記錄的結果,所以我們輸出這個結果。最後還是需要結束對象資源:
$db = null;

默認這個不是長連接,如果需要數據庫長連接,需要最後加一個參數:array(PDO::ATTR_PERSISTENT => true)變成這樣:
$db = new PDO($dsn, 'root', '', array(PDO::ATTR_PERSISTENT => true));

一次操作就這麼簡單,也許跟以前的沒有太大區別,跟ADOdb倒是有幾分相似。

使用setFetchMode方法來設置獲取結果集的返回值的類型,同樣類型還有:

PDO::FETCH_ASSOC -- 關聯數組形式
PDO::FETCH_NUM -- 數字索引數組形式
PDO::FETCH_BOTH -- 兩者數組形式都有,這是缺省的

PDO::FETCH_OBJ -- 按照對象的形式,類似於以前的 mysql_fetch_object()

$db->query($sql); 當$sql 中變量可以用$dbh->quote($params); //轉義字符串的數據  

php pdo statement

PDOStatement::bindColumn — 綁定一列到一個 PHP 變量  
PDOStatement::bindParam — 綁定一個參數到指定的變量名  
PDOStatement::bindValue — 把一個值綁定到一個參數  
PDOStatement::closeCursor — 關閉游標,使語句能再次被執行。  
PDOStatement::columnCount — 返回結果集中的列數  
PDOStatement::debugDumpParams — 打印一條 SQL 預處理命令  
PDOStatement::errorCode — 獲取跟上一次語句句柄操作相關的 SQLSTATE  
PDOStatement::errorInfo — 獲取跟上一次語句句柄操作相關的擴展錯誤信息  
PDOStatement::execute — 執行一條預處理語句  
PDOStatement::fetch — 從結果集中獲取下一行  
PDOStatement::fetchAll — 返回一個包含結果集中所有行的數組  
PDOStatement::fetchColumn — 從結果集中的下一行返回單獨的一列。  
PDOStatement::fetchObject — 獲取下一行並作為一個對象返回。  
PDOStatement::getAttribute — 檢索一個語句屬性  
PDOStatement::getColumnMeta — 返回結果集中一列的元數據  
PDOStatement::nextRowset — 在一個多行集語句句柄中推進到下一個行集  
PDOStatement::rowCount — 返回受上一個 SQL 語句影響的行數  
PDOStatement::setAttribute — 設置一個語句屬性  
PDOStatement::setFetchMode — 為語句設置默認的獲取模式。 

插入,更新,刪除數據,

$db->exec("DELETE FROM `xxxx_menu` where mid=43");

講一下PDO中的事務

PDO->beginTransaction(),PDO->commit(),PDO->rollBack()這三個方法是在支持回滾功能時一起使用的。PDO->beginTransaction()方法標明起始點,PDO->commit()方法標明回滾結束點,並執行SQL,PDO->rollBack()執行回滾。

<?php
try {
$dbh = new PDO('mysql:host=localhost;dbname=test', ‘root', ”);
$dbh->query('set names utf8;');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$dbh->beginTransaction();
$dbh->exec(”INSERT INTO `test`.`table` (`name` ,`age`)VALUES ('mick', 22);”);
$dbh->exec(”INSERT INTO `test`.`table` (`name` ,`age`)VALUES ('lily', 29);”);
$dbh->exec(”INSERT INTO `test`.`table` (`name` ,`age`)VALUES ('susan', 21);”);
$dbh->commit();

} catch (Exception $e) {
$dbh->rollBack();
echo “Failed: ” . $e->getMessage();
}
?>
現在你已經通過PDO建立了連接,在部署查詢之前你必須搞明白PDO是怎樣管理事務的。如果你以前從未遇到過事務處理,(現在簡單介紹一下:)它們提供了4個主要的特性:原子性,一致性,獨立性和持久性(Atomicity, Consistency, Isolation and Durability,ACID)通俗一點講,一個事務中所有的工作在提交時,即使它是分階段執行的,也要保證安全地應用於數據庫,不被其他的連接干擾。事務工作也可以在請求發生錯誤時輕松地自動取消。

事務的典型運用就是通過把批量的改變“保存起來”然後立即執行。這樣就會有徹底地提高更新效率的好處。換句話說,事務可以使你的腳本更快速同時可能更健壯(要實現這個優點你仍然需要正確的使用它們)。

不幸運的是,並不是每個數據庫都支持事務,因此PDO需要在建立連接時運行在被認為是“自動提交”的模式下。自動提交模式意味著你執行的每個查詢都有它自己隱含的事務處理,無論數據庫支持事務還是因數據庫不支持而不存在事務。如果你需要一個事務,你必須使用 PDO->beginTransaction() 方法創建一個。如果底層驅動不支持事務處理,一個PDOException就會被拋出(與你的異常處理設置無關,因為這總是一個嚴重的錯誤狀態)。在一個事物中,你可以使用 PDO->commit() 或 PDO->rollBack() 結束它,這取決於事務中代碼運行是否成功。

當腳本結束時或一個連接要關閉時,如果你還有一個未處理完的事務,PDO將會自動將其回滾。這是對於腳本意外終止的情況來說是一個安全的方案——如果你沒有明確地提交事務,它將會假設發生了一些錯誤,為了你數據的安全,所以就執行回滾了。

PDOException

PDO 提供了3中不同的錯誤處理策略。
1. PDO::ERRMODE_SILENT
這是默認使用的模式。PDO會在statement和database對象上設定簡單的錯誤代號,你可以使用PDO->errorCode() 和 PDO->errorInfo() 方法檢查錯誤;如果錯誤是在對statement對象進行調用時導致的,你就可以在那個對象上使用 PDOStatement->errorCode() 或 PDOStatement->errorInfo() 方法取得錯誤信息。而如果錯誤是在對database對象調用時導致的,你就應該在這個database對象上調用那兩個方法。
2. PDO::ERRMODE_WARNING
作為設置錯誤代號的附加,PDO將會發出一個傳統的E_WARNING信息。這種設置在除錯和調試時是很有用的,如果你只是想看看發生了什麼問題而不想中斷程序的流程的話。
3. PDO::ERRMODE_EXCEPTION
作為設置錯誤代號的附件,PDO會拋出一個PDOException異常並設置它的屬性來反映錯誤代號和錯誤信息。這中設置在除錯時也是很有用的,因為他會有效的“放大(blow up)”腳本中的出錯點,非常快速的指向一個你代碼中可能出錯區域。(記住:如果異常導致腳本中斷,事務處理回自動回滾。)
異常模式也是非常有用的,因為你可以使用比以前那種使用傳統的PHP風格的錯誤處理結構更清晰的結構處理錯誤,比使用安靜模式使用更少的代碼及嵌套,也能夠更加明確地檢查每個數據庫訪問的返回值。
關於PHP中異常的更多信息請看Exceptions章節
PDO 使用基於SQL-92 SQLSTATE 的錯誤代號字符串;特定的PDO驅動應當將自己本身的代號對應到適當的SQLSTATE代號上。PDO->errorCode() 方法只返回單一的SQLSTATE代號。如果你需要關於一個錯誤的更加有針對性的信息,PDO也提供了一個PDO->errorInfo()方法,它可以返回一個包含了SQLSTATE代號,特定數據庫驅動的錯誤代號和特定數據庫驅動的錯誤說明字符串。

<?php
// 修改默認的錯誤顯示級別
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
?>

PDO常用方法:

PDO::query() 主要用於有記錄結果返回的操作,特別是select操作。
PDO::exec()主要是針對沒有結果集合返回的操作。如insert,update等操作。返回影響行數。
PDO::lastInsertId()返回上次插入操作最後一條ID,但要注意:如果用insert into tb(col1,col2)values(v1,v2),(v11,v22)..的方式一次插入多條記錄,lastinsertid()返回的只是第一條(v1,v2)插入時的ID,而不是最後一條記錄插入的記錄ID。
PDOStatement::fetch()是用來獲取一條記錄。配合while來遍歷。
PDOStatement::fetchAll()是獲取所有記錄集到一個中。
PDOStatement::fetchcolumn([intcolumn_indexnum])用於直接訪問列,參數column_indexnum是該列在行中的從0開始索引值,但是,這個方法一次只能取得同一行的一列,只要執行一次,就跳到下一行。因此,用於直接訪問某一列時較好用,但要遍歷多列就用不上。
PDOStatement::rowcount()適用於當用query("select...")方法時,獲取記錄的條數。也可以用於預處理中。$stmt->rowcount();
PDOStatement::columncount()適用於當用query("select...")方法時,獲取記錄的列數。

注解:
1、選fetch還是fetchall?

小記錄集時,用fetchall效率高,減少從數據庫檢索次數,但對於大結果集,用fetchall則給系統帶來很大負擔。數據庫要向WEB前端傳輸量太大反而效率低。
2、fetch()或fetchall()有幾個參數:
mixed pdostatement::fetch([int fetch_style[,int cursor_orientation [,int cursor_offset]]])
array pdostatement::fetchAll(int fetch_style)

更多的PDO方法:

    PDO::beginTransaction — 啟動一個事務  
    PDO::commit — 提交一個事務  
    PDO::__construct — 創建一個表示數據庫連接的 PDO 實例  
    PDO::errorCode — 獲取跟數據庫句柄上一次操作相關的 SQLSTATE  
    PDO::errorInfo — Fetch extended error information associated with the last operation on the database handle  
    PDO::exec — 執行一條 SQL 語句,並返回受影響的行數  
    PDO::getAttribute — 取回一個數據庫連接的屬性  
    PDO::getAvailableDrivers — 返回一個可用驅動的數組  
    PDO::inTransaction — 檢查是否在一個事務內  
    PDO::lastInsertId — 返回最後插入行的ID或序列值  
    PDO::prepare — Prepares a statement for execution and returns a statement object  
    PDO::query — Executes an SQL statement, returning a result set as a PDOStatement object  
    PDO::quote — Quotes a string for use in a query.  
    PDO::rollBack — 回滾一個事務  
    PDO::setAttribute — 設置屬性  
    Exception::getMessage — 獲取異常消息內容。  
    Exception::getPrevious — 返回異常鏈中的前一個異常  
    Exception::getCode — 獲取異常代碼  
    Exception::getFile — 獲取發生異常的程序文件名稱  
    Exception::getLine — 獲取發生異常的代碼在文件中的行號  
    Exception::getTrace — 獲取異常追蹤信息  
    Exception::getTraceAsString — 獲取字符串類型的異常追蹤信息  
    Exception::toString — 將異常對象轉換為字符串  
    Exception::clone — 異常克隆  

屬性列表:

PDO::PARAM_BOOL
表示一個布爾類型
PDO::PARAM_NULL
表示一個SQL中的NULL類型
PDO::PARAM_INT
表示一個SQL中的INTEGER類型
PDO::PARAM_STR
表示一個SQL中的SQL CHAR,VARCHAR類型
PDO::PARAM_LOB
表示一個SQL中的large object類型
PDO::PARAM_STMT
表示一個SQL中的recordset類型,還沒有被支持
PDO::PARAM_INPUT_OUTPUT
Specifies that the parameter is an INOUT parameter for a stored procedure. You must bitwise-OR this value with an explicit PDO::PARAM_* data type.
PDO::FETCH_LAZY
將每一行結果作為一個對象返回
PDO::FETCH_ASSOC
僅僅返回以鍵值作為下標的查詢的結果集,名稱相同的數據只返回一個
PDO::FETCH_NAMED
僅僅返回以鍵值作為下標的查詢的結果集,名稱相同的數據以數組形式返回
PDO::FETCH_NUM
僅僅返回以數字作為下標的查詢的結果集
PDO::FETCH_BOTH
同時返回以鍵值和數字作為下標的查詢的結果集
PDO::FETCH_OBJ
以對象的形式返回結果集
PDO::FETCH_BOUND
將PDOStatement::bindParam()和PDOStatement::bindColumn()所綁定的值作為變量名賦值後返回
PDO::FETCH_COLUMN
表示僅僅返回結果集中的某一列
PDO::FETCH_CLASS
表示以類的形式返回結果集
PDO::FETCH_INTO
表示將數據合並入一個存在的類中進行返回
PDO::FETCH_FUNC
PDO::FETCH_GROUP
PDO::FETCH_UNIQUE
PDO::FETCH_KEY_PAIR
以首個鍵值下表,後面數字下表的形式返回結果集
PDO::FETCH_CLASSTYPE
PDO::FETCH_SERIALIZE
表示將數據合並入一個存在的類中並序列化返回
PDO::FETCH_PROPS_LATE
Available since PHP 5.2.0
PDO::ATTR_AUTOCOMMIT
在設置成true的時候,PDO會自動嘗試停止接受委托,開始執行
PDO::ATTR_PREFETCH
設置應用程序提前獲取的數據大小,並非所有的數據庫哦度支持
PDO::ATTR_TIMEOUT
設置連接數據庫超時的值
PDO::ATTR_ERRMODE
設置Error處理的模式
PDO::ATTR_SERVER_VERSION
只讀屬性,表示PDO連接的服務器端數據庫版本
PDO::ATTR_CLIENT_VERSION
只讀屬性,表示PDO連接的客戶端PDO驅動版本
PDO::ATTR_SERVER_INFO
只讀屬性,表示PDO連接的服務器的meta信息
PDO::ATTR_CONNECTION_STATUS
PDO::ATTR_CASE
通過PDO::CASE_*中的內容對列的形式進行操作
PDO::ATTR_CURSOR_NAME
獲取或者設定指針的名稱
PDO::ATTR_CURSOR
設置指針的類型,PDO現在支持PDO::CURSOR_FWDONLY和PDO::CURSOR_FWDONLY
PDO::ATTR_DRIVER_NAME
返回使用的PDO驅動的名稱
PDO::ATTR_ORACLE_NULLS
將返回的空字符串轉換為SQL的NULL
PDO::ATTR_PERSISTENT
獲取一個存在的連接
PDO::ATTR_STATEMENT_CLASS
PDO::ATTR_FETCH_CATALOG_NAMES
在返回的結果集中,使用自定義目錄名稱來代替字段名。
PDO::ATTR_FETCH_TABLE_NAMES
在返回的結果集中,使用自定義表格名稱來代替字段名。
PDO::ATTR_STRINGIFY_FETCHES
PDO::ATTR_MAX_COLUMN_LEN
PDO::ATTR_DEFAULT_FETCH_MODE
Available since PHP 5.2.0
PDO::ATTR_EMULATE_PREPARES
Available since PHP 5.1.3.
PDO::ERRMODE_SILENT
發生錯誤時不匯報任何的錯誤信息,是默認值
PDO::ERRMODE_WARNING
發生錯誤時發出一條php的E_WARNING的信息
PDO::ERRMODE_EXCEPTION
發生錯誤時拋出一個PDOException
PDO::CASE_NATURAL
回復列的默認顯示格式
PDO::CASE_LOWER
強制列的名字小寫
PDO::CASE_UPPER
強制列的名字大寫
PDO::NULL_NATURAL
PDO::NULL_EMPTY_STRING
PDO::NULL_TO_STRING
PDO::FETCH_ORI_NEXT
獲取結果集中的下一行數據,僅在有指針功能時有效
PDO::FETCH_ORI_PRIOR
獲取結果集中的上一行數據,僅在有指針功能時有效
PDO::FETCH_ORI_FIRST
獲取結果集中的第一行數據,僅在有指針功能時有效
PDO::FETCH_ORI_LAST
獲取結果集中的最後一行數據,僅在有指針功能時有效
PDO::FETCH_ORI_ABS
獲取結果集中的某一行數據,僅在有指針功能時有效
PDO::FETCH_ORI_REL
獲取結果集中當前行後某行的數據,僅在有指針功能時有效
PDO::CURSOR_FWDONLY
建立一個只能向後的指針操作對象
PDO::CURSOR_SCROLL
建立一個指針操作對象,傳遞PDO::FETCH_ORI_*中的內容來控制結果集
PDO::ERR_NONE (string)
設定沒有錯誤時候的錯誤信息
    <?php  
    $dbh = new PDO('mysql:host=localhost;dbname=access_control', 'root', '');    
    $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);    
    $dbh->exec('set names utf8');   
    /*添加*/  
    //$sql = "INSERT INTO `user` SET `login`=:login AND `password`=:password";   
    $sql = "INSERT INTO `user` (`login` ,`password`)VALUES (:login, :password)";  $stmt = $dbh->prepare($sql);  $stmt->execute(array(':login'=>'kevin2',':password'=>''));    
    echo $dbh->lastinsertid();    
    /*修改*/  
    $sql = "UPDATE `user` SET `password`=:password WHERE `user_id`=:userId";    
    $stmt = $dbh->prepare($sql);    
    $stmt->execute(array(':userId'=>'7', ':password'=>'4607e782c4d86fd5364d7e4508bb10d9'));    
    echo $stmt->rowCount();   
    /*刪除*/  
    $sql = "DELETE FROM `user` WHERE `login` LIKE 'kevin_'"; //kevin%    
    $stmt = $dbh->prepare($sql);    
    $stmt->execute();    
    echo $stmt->rowCount();    
    /*查詢*/  
    $login = 'kevin%';    
    $sql = "SELECT * FROM `user` WHERE `login` LIKE :login";    
    $stmt = $dbh->prepare($sql);    
    $stmt->execute(array(':login'=>$login));    
    while($row = $stmt->fetch(PDO::FETCH_ASSOC)){       
     print_r($row);    
    }    
    print_r( $stmt->fetchAll(PDO::FETCH_ASSOC));   
    ?>  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved