超輕的 PHP 數(shù)據(jù)庫(kù)工具包[轉(zhuǎn)]
2011-10-15 11:45:37| 分類: 程序設(shè)計(jì) |舉報(bào) |字號(hào) 訂閱
一個(gè)很輕的 PHP 數(shù)據(jù)庫(kù)工具包,誕生時(shí)間兩天(足以證明很輕了)。 兩個(gè)類,一個(gè) Connection 管理 PDO 連接(支持多數(shù)據(jù)庫(kù)),一個(gè) QuickQuery 用來快速執(zhí)行數(shù)據(jù)庫(kù)操作(不用在 PDO 和 PDOStatement 之間來回折騰)
使用范例
01 |
use Persistence\DbAccess; |
04 |
DbAccess\Connection::add( |
12 |
$conn = DbAccess\Connection::instance( 'default' ); |
15 |
$query = new DbAccess\QuickQuery( $conn ); |
16 |
$query ->prepare( 'select :name as name' )->execute( array ( ':name' => 'sssssss' )); |
18 |
// 對(duì)象直接作為迭代器產(chǎn)生數(shù)據(jù)數(shù)組 |
19 |
foreach ( $query as $i ) { |
23 |
// 如果有偏執(zhí)的話,輸出響應(yīng)之前手動(dòng)斷開連接 |
24 |
DbAccess\Connection::disconnectAll(); |
[代碼] Persistence/DbAccess/QuickQuery.php
002 |
namespace Persistence\DbAccess; |
003 |
use PDO, ArrayObject, DateTime; |
004 |
use LogicException, InvalidArgumentException; |
010 |
* @author sssssss<ssssssss@testabc.com> |
012 |
* @license http://www./licenses/mit-license.html |
013 |
* @copyright StuCampus Development Team, Shenzhen University |
016 |
class QuickQuery implements \IteratorAggregate |
021 |
* @var \Persistence\DbAccess\Connection |
023 |
private $connection = null; |
030 |
private $stmt = null; |
037 |
private $checkedParams = array (); |
043 |
* @param \Persistence\DbAccess\Connection $connection 數(shù)據(jù)庫(kù)連接 |
045 |
public function __construct(Connection $connection ) |
047 |
$this ->connection = $connection ; |
053 |
* @param string $sqlCommand SQL語句 |
054 |
* @return \Persistence\DbAccess\QuickQuery |
056 |
public function prepare( $sqlCommand ) |
058 |
// 從連接獲取 PDO, 并對(duì) SQL 語句執(zhí)行 prepare, 產(chǎn)生 PDO Statement |
059 |
$this ->stmt = $this ->connection->getPDO()->prepare( $sqlCommand ); |
060 |
// 修改 PDO Statement 模式為關(guān)聯(lián)數(shù)組數(shù)據(jù) |
061 |
$this ->stmt->setFetchMode(PDO::FETCH_ASSOC); |
067 |
* 執(zhí)行數(shù)據(jù)查詢 |
069 |
* @throws PDOException |
070 |
* @return \Persistence\DbAccess\QuickQuery |
072 |
public function execute( $params = array ()) |
074 |
$stmt = $this ->getStatement(); |
077 |
$diff = array_diff ( $this ->checkedParams, array_keys ( $params )); |
078 |
if ( count ( $this ->checkedParams) && count ( $diff )) { |
079 |
throw new InvalidArgumentException( '缺少必備參數(shù):' .implode( ' | ' , $diff )); |
082 |
// 將 PHP 數(shù)據(jù)類型對(duì)應(yīng)到數(shù)據(jù)庫(kù)數(shù)據(jù)類型 |
083 |
foreach ( $params as $key => $value ) { |
087 |
$type = PDO::PARAM_INT; |
089 |
case is_bool ( $value ): |
090 |
$type = PDO::PARAM_BOOL; |
092 |
case ( $value instanceof DateTime): |
093 |
$type = PDO::PARAM_STR; |
094 |
$value = $value ->format(\DateTime::W3C); |
096 |
case is_null ( $value ): |
097 |
$type = PDO::PARAM_NULL; |
100 |
$type = PDO::PARAM_STR; |
103 |
$stmt ->bindValue( $key , $value , $type ); |
107 |
$this ->checkedParams = array (); // 清空參數(shù)檢查 |
112 |
* 獲取 Statement 對(duì)象 |
114 |
* 返回對(duì)象可以被綁定參數(shù)重新執(zhí)行, 也可以被當(dāng)作迭代器遍歷獲取數(shù)據(jù)。 |
116 |
* @return \PDOStatement |
118 |
public function getStatement() |
121 |
throw new LogicException( 'SQL語句應(yīng)該先被 QuickQuery.prepare 預(yù)處理' ); |
128 |
* getStatement 方法的替代名 |
130 |
* 實(shí)現(xiàn) PHP 標(biāo)準(zhǔn)庫(kù) 中的 IteratorAggregate 接口, 外部可以直接將本對(duì)象作為迭代器遍 |
131 |
* 歷。和 getStatment 唯一不同之處, 是本方法不會(huì)拋出 LogicException 異常。如果 |
132 |
* 沒有事先使用 prepare 和 execute, 會(huì)返回一個(gè)空迭代器。 |
134 |
* @return Traversable |
136 |
public function getIterator() |
139 |
return $this ->getStatement(); |
140 |
} catch (LogicException $ex ) { |
141 |
return new \ArrayObject(); |
148 |
* 通過此處導(dǎo)入的被檢查查詢參數(shù), 如果沒有得到賦值, 則查詢時(shí)會(huì)拋出 LogicException 異常。 |
150 |
* @param array $params |
151 |
* @return \Persistence\DbAccess\QuickQuery |
153 |
public function setParamsCheck( array $params ) |
155 |
$this ->checkedParams = $params ; |
161 |
* 將結(jié)果集轉(zhuǎn)換為數(shù)組 |
165 |
public function toArray() |
167 |
return iterator_to_array( $this ->getStatement()); |
171 |
* 獲取最后一個(gè)插入結(jié)果(或序列)的 ID |
173 |
* @param string $name |
176 |
public function getLastInsertId( $name =null) |
178 |
return $this ->connection->getPDO()->lastInsertId( $name ); |
[代碼] Persistence/DbAccess/Connection.php
002 |
namespace Persistence\DbAccess; |
003 |
use InvalidArgumentException, BadMethodCallException; |
004 |
use PDO, PDOException; |
007 |
* 連接工廠,提供全局的PDO對(duì)象,并管理事務(wù)。 |
010 |
* @author sssssss<ssssssss@testabc.com> |
012 |
* @license http://www./licenses/mit-license.html |
013 |
* @copyright StuCampus Development Team, Shenzhen University |
016 |
final class Connection |
019 |
* Connector 實(shí)例集合 |
023 |
static private $instances = array (); |
026 |
* 數(shù)據(jù)庫(kù)驅(qū)動(dòng)名 |
030 |
private $driver = '' ; |
033 |
* 數(shù)據(jù)庫(kù)連接字符串(Database Source Name) |
051 |
private $username = '' ; |
058 |
private $password = '' ; |
065 |
private $isPersisten = false; |
072 |
private $isEmulate = false; |
079 |
private $isInTransation = false; |
082 |
* 私有構(gòu)造函數(shù),阻止外部使用 new 操作符實(shí)例化 |
084 |
private function __construct(){} |
087 |
* 生產(chǎn) Connector 實(shí)例(多例) |
089 |
* @param string $name |
090 |
* @return \StuCampus\DataModel\Connector |
092 |
static public function getInstance( $name = 'default' ) |
094 |
if (!isset(self:: $instances [ $name ])) { |
095 |
// 如果訪問的實(shí)例不存在則拋出錯(cuò)誤異常 |
096 |
throw new InvalidArgumentException( "[{$name}] 不存在" ); |
099 |
return self:: $instances [ $name ]; |
103 |
* 斷開所有數(shù)據(jù)庫(kù)實(shí)例的連接 |
105 |
static public function disconnectAll() |
107 |
foreach (self:: $instances as $instance ) { |
108 |
$instance ->disconnect(); |
115 |
* 向?qū)嵗禾砑?Connector |
117 |
* @param string $name 標(biāo)識(shí)名 |
118 |
* @param string $driver 驅(qū)動(dòng)名 |
119 |
* @param string $dsn 連接字符串 |
120 |
* @param string $usr 數(shù)據(jù)庫(kù)用戶名 |
121 |
* @param string $pwd 數(shù)據(jù)庫(kù)密碼 |
122 |
* @param bool $emulate 仿真預(yù)編譯查詢 |
123 |
* @param bool $persisten 是否持久連接 |
125 |
static public function registry( $name , $driver , $dsn , $usr , $pwd , $emulate = false, $persisten = false) |
127 |
if (isset(self:: $instances [ $name ])) { |
128 |
// 如果添加的實(shí)例名已經(jīng)存在則拋出異常 |
129 |
throw new BadMethodCallException( "[{$name}] 已被注冊(cè)" ); |
132 |
// 實(shí)例化自身,并推入數(shù)組中 |
133 |
self:: $instances [ $name ] = new self(); |
134 |
self:: $instances [ $name ]->dsn = $driver . ':' . $dsn ; |
135 |
self:: $instances [ $name ]->username = $usr ; |
136 |
self:: $instances [ $name ]->password = $pwd ; |
137 |
self:: $instances [ $name ]->driver = $driver ; |
138 |
self:: $instances [ $name ]->isPersisten = (bool) $persisten ; |
139 |
self:: $instances [ $name ]->isEmulate = (bool) $emulate ; |
143 |
* 獲取 PHP Database Object |
147 |
public function getPDO() |
150 |
// 檢查 PDO 是否已經(jīng)實(shí)例化,否則先實(shí)例化 PDO |
151 |
$this ->pdo = new PDO( $this ->dsn, $this ->username, $this ->password); |
152 |
// 錯(cuò)誤模式為拋出 PDOException 異常 |
153 |
$this ->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); |
155 |
$this ->pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, $this ->isEmulate); |
157 |
$this ->pdo->setAttribute(PDO::ATTR_PERSISTENT, $this ->isPersisten); |
165 |
* 獲取數(shù)據(jù)庫(kù)驅(qū)動(dòng)名 |
169 |
public function getDriverName() |
171 |
return $this ->driver; |
177 |
public function transationBegin() |
179 |
$this ->isInTransation = $this ->getPDO()->beginTransaction(); |
185 |
public function transationCommit() |
187 |
if ( $this ->isInTransation) { |
188 |
$this ->getPDO()->commit(); |
190 |
trigger_error( 'transationBegin 應(yīng)該先于 transationCommit 調(diào)用' ); |
198 |
public function transationRollback() |
200 |
if ( $this ->isInTransation) { |
201 |
$this ->getPDO()->rollBack(); |
203 |
trigger_error( 'transationBegin 應(yīng)該先于 transationRollback 調(diào)用' ); |
212 |
public function isInTransation() |
214 |
return $this ->isInTransation; |
218 |
* 在事務(wù)中執(zhí)行回調(diào)函數(shù) |
220 |
* @param function $callback 匿名函數(shù)或閉包函數(shù) |
221 |
* @param bool $autoRollback 異常發(fā)生時(shí)是否自動(dòng)回滾 |
222 |
* @throws \PDOException |
225 |
public function transationExecute( $callback , $autoRollback = true) |
229 |
$this ->transationBegin(); |
230 |
// 調(diào)用回調(diào)函數(shù) |
231 |
if ( is_callable ( $callback )) { |
234 |
throw new InvalidArgumentException( '$callback應(yīng)該為回調(diào)函數(shù)' ); |
237 |
return $this ->transationCommit(); |
238 |
} catch(PDOException $pex ) { |
239 |
// 如果開啟了自動(dòng)回滾, 則捕捉到 PDO 異常時(shí)先回滾再拋出 |
241 |
$this ->transationRollback(); |
248 |
* 安全地?cái)嚅_數(shù)據(jù)庫(kù)連接 |
250 |
public function disconnect() |
253 |
// 檢查 PDO 是否已經(jīng)實(shí)例化,是則設(shè)置為null |
261 |
public function __clone() |
263 |
trigger_error( '被阻止的 __clone 方法, Connector 是單例類' ); |
|