與任何其他資料庫擴充一樣,PDO可以直接從所選資料建立現有類別的實例。但是,與其他擴充不同的是,PDO為強大而靈活的物件操作提供了許多特性。
取得單一物件
#要從查詢結果建立單一對象,有兩種方法。
1.使用熟悉的fetch()方法:
class User {}; $stmt = $pdo->query('SELECT name FROM users LIMIT 1'); $stmt->setFetchMode(PDO::FETCH_CLASS, 'User'); $user = $stmt->fetch();
2.專用的fetchObject()方法:
class User {}; $user = $pdo->query('SELECT name FROM users LIMIT 1')->fetchObject('User');
雖然這兩個程式碼段都將為你提供相同的User類別實例,
/* object(User)#3 (1) { ["name"] => string(4) "John" } */
後一種方法看起來絕對更簡潔。此外,如果使用了fetch()方法,但是沒有使用這樣的名稱定義類,則將靜默傳回一個數組,而使用fetchObject()將拋出一個適當的錯誤。
取得物件陣列
當然,上面描述的兩種方法都可以與一個熟悉的while語句一起使用,從資料庫中取得結果行。
使用一個方便的fetchAll()方法一次取得物件陣列中所有傳回的記錄:
class User {}; $users = $pdo->query('SELECT name FROM users')->fetchAll(PDO::FETCH_CLASS, 'User');
將給你一個數組,由一個User類別的物件組成,返回資料填充屬性:
/* array(2) { [0]=> object(User)#3 (1) { ["name"] => string(4) "John" } [1]=> object(User)#4 (1) { ["name"]=> string(4) "Mike" } } */
注意,你可以將此模式與PDO::FETCH_UNIQUE和PDO::FETCH_GROUP組合使用,以獲得由唯一欄位索引的結果數組,或分別使用非唯一欄位對結果進行分組。
例如,下面的程式碼將傳回一個數組,其中記錄id將用作數組索引而不是連續數字。
class User {}; $stmt = $pdo->query('SELECT id, id, name, car FROM users'); $users = ->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_UNIQUE, 'User');
指派類別屬性
無論選擇哪一種方法,查詢傳回的所有欄位都會依照下列規則指派給對應的類別屬性:
1.如果有一個類別屬性,它的名稱與列名相同,則將為該屬性分配列值
2.如果沒有這樣的屬性,那麼將呼叫一個魔術方法__set()
3.如果沒有為該類別定義__set()方法,那麼將建立一個公共屬性並為其指派一個列值。
例如,這段程式碼
class User { public $name; } $user = $pdo->query('SELECT * FROM users LIMIT 1')->fetchObject('User');
將給你一個對象,所有屬性自動分配,無論它們是否存在於類別中:
/* object(User)#3 (4) { ["id"] => string(3) "104" ["name"] => string(4) "John" ["sex"] => string(4) "male" ["car"] => string(6) "Toyota" } */
從這一點可以看出,為了避免自動建立屬性,你可以使用魔術方法__set()過濾掉屬性。最簡單的過濾技巧就是一個空的__set()方法。使用它,只會設定現有的屬性:
class User { private $name; public function __set($name, $value) {} } $user = $pdo->query('SELECT * FROM users LIMIT 1')->fetchObject('User'); /* array(1) { [0]=> object(User)#3 (1) { ["name":"User":private]=> string(4) "John" } } */
如上PDO還可以為私有屬性指派值。
將建構子參數傳遞給物件
#當然,對於新建立的對象,我們可能需要提供建構子參數。為此,fetchObject()和fetchAll()方法都有一個專用的參數,你可以用它以陣列的形式傳遞建構函式參數。
假設我們有一個類別User,它有一個car屬性,可以透過提供的變數在建構函數中設定:
class User { public function __construct($car) { $this->car = $car; } }
在取得記錄時,我們應該加入一個帶有建構函數參數的陣列:
$users = $pdo->query('SELECT name FROM users LIMIT 1') ->fetchAll(PDO::FETCH_CLASS, 'User', ['Caterpillar']); $user = $pdo->query('SELECT name FROM users LIMIT 1') ->fetchObject('User',['Caterpillar']);
/* object(User)#3 (2) { ["name"] => string(4) "John" ["car"] => string(11) "Caterpillar" } */
可以看到,資料庫中的值被覆寫了,因為預設情況下PDO在呼叫建構子之前分配類別屬性。這可能是一個問題,但很容易解決:
在呼叫建構子後設定類別屬性
##mysql_fetch_object()註解:
如果你使用mysql_fetch_object並指定一個類別-屬性將在建構子執行之前設定。這通常不是問題,但是如果你的屬性是透過__set()魔術方法設定的,那必須先執行建構函數邏輯,否則可能會導致一些主要問題。
可惜mysql是一個mysqli擴展,但我們使用的是PDO。因此,有一種方法可以告訴PDO在建構子執行之後分配屬性。為此,必須使用PDO::FETCH_PROPS_LATE常數。 使用fetchAll()會非常簡單,class User { public function __construct($car) { $this->car = $car; } } $stmt = $pdo->query('SELECT name, car FROM users LIMIT 1'); $users = $stmt->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'User', ['Caterpillar']);
class User { public function __construct($car) { $this->car = $car; } } $stmt = $pdo->query('SELECT name, car FROM users LIMIT 1'); $stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'User'); $user = $stmt->fetchObject('User', ['Caterpillar']); /* object(User)#3 (2) { ["car"] => string(6) "Toyota" ["name"] => string(4) "John" } */
$stmt = $pdo->query('SELECT name, car FROM users LIMIT 1'); $stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'User', ['Caterpillar']); $user = $stmt->fetch();
從資料庫中取得類別名稱
還有一個更有趣的標誌,它告訴PDO從第一列的值中取得類名。使用這個標誌,可以避免使用setFetchMode()和fetch():$data = $pdo->query("SELECT 'User', name FROM users") ->fetch(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE); /* object(User)#3 (1) { ["name"]=> string(4) "John" } */
class Male {}; class Female {}; $stmt = $pdo->query('SELECT sex, name FROM users'); $users = $stmt->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE); /* array(6) { [0]=> object(Male)#3 (1) { ["name"]=> string(4) "John" } [1]=> object(Male)#4 (1) { ["name"]=> string(4) "Mike" } [2]=> object(Female)#5 (1) { ["name"]=> string(4) "Mary" } [3]=> object(Female)#6 (1) { ["name"]=> string(5) "Kathy" } }*/
更新現有物件#
除了创建新对象,PDO还可以更新现有对象。只使用setFetchMode(),它将现有变量作为参数。显然,使用fetchAll()是无用的。
class User { public $name; public $state; public function __construct() { $this->name = NULL; } } $user = new User; $user->state = "up'n'running"; var_dump($user); $stmt = $pdo->query('SELECT name FROM users LIMIT 1'); $stmt->setFetchMode(PDO::FETCH_INTO, $user); $data = $stmt->fetch(); var_dump($data, $user); /* object(Foo)#2 (2) { ["name"] => NULL ["state"] => string(12) "up'n'running" } object(Foo)#2 (2) { ["name"] => string(4) "John" ["state"] => string(12) "up'n'running" } object(Foo)#2 (2) { ["name"] => string(4) "John" ["state"] => string(12) "up'n'running" } */
如上,fetch()调用返回的是相同的对象,这在我看来是多余的。还要注意,与PDO::FETCH_CLASS不同,这种模式不分配私有属性。
以上是如何取得PDO物件並設定屬性? (代碼詳解)的詳細內容。更多資訊請關注PHP中文網其他相關文章!