PHP Conference Japan 2024

PDOStatement::fetchObject

(PHP 5 >= 5.1.0, PHP 7, PHP 8, PECL pdo >= 0.2.4)

PDOStatement::fetchObject擷取下一列並將其作為物件傳回

說明

public PDOStatement::fetchObject(?string $class = "stdClass", array $constructorArgs = []): object|false

擷取下一列並將其作為物件返回。此函式是 PDOStatement::fetch() 搭配 PDO::FETCH_CLASSPDO::FETCH_OBJ 風格的替代方案。

擷取物件時,會從相對應的欄位值賦值給其屬性,然後呼叫其建構子。

參數

class

所建立類別的名稱。

constructorArgs

此陣列的元素會傳遞給建構子。

傳回值

返回具有與欄位名稱相對應之屬性名稱的所需類別實例,或者在失敗時返回 false

錯誤/例外

如果屬性 PDO::ATTR_ERRMODE 設定為 PDO::ERRMODE_WARNING,則會發出層級為 E_WARNING 的錯誤。

如果屬性 PDO::ATTR_ERRMODE 設定為 PDO::ERRMODE_EXCEPTION,則會拋出 PDOException

另請參閱

新增註解

使用者貢獻的註解 6 則註解

rasmus at mindplay dot dk
11 年前
請注意 PDOStatement::fetchObject() 的非正統行為,它在呼叫建構子*之前*注入屬性值 - 換句話說,如果您的類別在建構子中將屬性值初始化為預設值,您將覆蓋 fetchObject() 注入的值!

在您的 __construct() 方法中使用 var_dump($this) 將顯示在呼叫建構子之前已初始化屬性值,因此請小心。

因此,我強烈建議您在將資料作為陣列擷取之後手動水合您的物件,而不是嘗試讓 PDO 直接將屬性套用到您的物件。

顯然有人認為他們在這裡很聰明 - 允許您從建構子存取水合的屬性值。不幸的是,這不是 OOP 的運作方式 - 根據定義,建構子是在建構時呼叫的第一個方法。

如果您需要在建構和水合物件之後初始化它們,我建議您的模型類型實現一個帶有 init() 方法的介面,並且您的資料存取層在水合之後呼叫此方法(如果已實現)。
Val Bancer
4 年前
如果您希望在 `fetchObject` 設定屬性*之前*呼叫建構子,則應使用帶有 `PDO::FETCH_PROPS_LATE` 參數的 `PDOStatement::fetch` 方法。
beinghavingbreackfast at gmail dot com
9 年前
應該提到的是,此方法甚至可以設定非公開屬性。這聽起來可能很奇怪,但在根據 mysql 結果建立物件時實際上非常有用。
考慮一個使用者類別

<?php
類別 User {
// 私有屬性
私有 $id, $name;

私有 函式
__construct () {}

公開 靜態 函式
load_by_id ($id) {
$stmt = $pdo->prepare('SELECT id, name FROM users WHERE id=?');
$stmt->execute([$id]);
返回
$stmt->fetchObject(__CLASS__);
}
/* 使用 "name" 欄位/屬性也可以寫出相同的函式 */
}

$user = User::load_by_id(1);
var_dump($user);
?>

fetchObject() 不會在意屬性是公開或私有。它只是將結果傳遞給物件。輸出如下:

物件(User)#3 (2) {
["id":"User":私有]=>
字串(1) "1"
["name":"User":私有]=>
字串(10) "John Smith"
}
sebastian dot rapetti at alice dot it
7 年前
PDOStatement::fetchObject() 將值以字串形式注入,我需要進行類型轉換。

我在類別建構式中加入了 settype() 函式來完成這件事

以下是用 id 搜尋使用者並返回使用者物件實例的函式

<?php
類別 UserMapper 繼承 MapperAbstract
{
//其他程式碼
公開 函式 findById(整數 $userId)
{
$pdos = $this->dBase->prepare('SELECT user_id AS objectId, name, description, password, active, created,
last_update AS lastUpdate FROM user WHERE user_id = :id'
);

$pdos->bindParam(':id', $userId, \PDO::PARAM_INT);
$pdos->execute();

返回
$pdos->fetchObject('\DomainObjects\User', 陣列($this->password));
}
//其他程式碼
}
?>

具有類型處理的 User 類別

<?php
類別 User 繼承 DomainObjectAbstract
{
//其他程式碼
public function __construct(Password $password)
{
$this->passwordUtility = $password;

settype($this->objectId, 'integer');
settype($this->active, 'integer');
}
//其他程式碼
}
?>

返回 User 實例的 var_dump() 結果

<?php
物件
(DomainObjects\User)[18]
公開
'name' => 字串 'root' (長度=4)
公開
'description' => 字串 'System User' (長度=11)
公開
'password' => 字串 '$2y$11$4IAn6SRaB0osPz8afZC5D.CmTrBGxnb5FQEygPjDirK9SWE/u8YuO' (長度=60)
公開
'active' => 整數 1
公開 'created' => 字串 '2015-02-14 10:39:00' (長度=19)
公開
'lastUpdate' => 字串 '2016-08-30 18:46:56' (長度=19)
私有
'passwordUtility' =>
物件(Auth\Password)[13]
保護
'options' =>
陣列 (
大小=1)
'cost' => 整數 11
保護 'objectId' => 整數 1
?>

「objectId」和「active」現在已是所需的類型
zlk1214 at gmail dot com
8 年前
您可以用物件導向的方式存取 MySQL 資料表。假設您有一個名為 Users 的資料表,其中包含 UserID、UserName、UserPassword、UserBirthday 等欄位,您可以建立一個繼承 DataObject 的 PHP 類別,並將其與此資料表關聯。
<?php
class User extends DataObject {
// name: Table Name, key: Primary Key (can be an array), auto: AUTO_INCREMENT field
protected static $_table = array('name' => 'Users', 'key' => 'UserID', 'auto' => 'UserID');
// relationships between PHP properties and MySQL field names
protected static $_propertyList = array('id' => 'UserID', 'name' => 'UserName', 'password' => 'UserPassword', 'birthday' => 'UserBirthday');

// A method that fetches all users as an array
public static function GetAll() {
global
$dbh;
$sql = 'SELECT * FROM Users';
$stmt = $dbh->query($sql);
$users = array();
while (
$user = $stmt->fetchObject(__CLASS__)) {
$users[] = $user;
}
return
$users;
}
// Methods that fetch a specific user
public static function GetUserByName($name) {}
public static function
GetUserByID($name) {}

// Methods for the current user object
public function checkPassword($password) {return $this->password == $password;}
public function
showLink() {return "<a href=\"user.php?i={$this->id}\">{$this->name}</a>";}
}

// Then, you can create an instance of this class to insert a row in your table
$user = new User();
$user->name = 'oct1158';
$user->password = '789012';
$user->useFunction('birthday', 'NOW()');
echo
'Field birthday uses MySQL Function: ', $user->birthday, '<br>';
if (
$user->insert()) {
echo
'New User ID: ', $user->id, '<br>';

// Update the row
$user->password = '112233';
$user->update();
} else {
echo
'INSERT Failed<br>';
}
// Get a specific user by a query
$sql = 'SELECT * FROM Users WHERE UserName = ?';
$stmt = $dbh->prepare($sql);
$stmt->execute(array('admin'));
$admin_user = $stmt->fetchObject('User');
echo
'Admin ID is ', $admin_user->id, '.<br>';
echo
'Admin Birthday is ', $admin_user->birthday, '.<br>';

// Get all users by a static method of that class
$users = User::GetAll();
echo
'<br>';
echo
$users[0]->name, ', ', $users[0]->birthday, '<br>';
echo
$users[1]->name, ', ', $users[1]->birthday, '<br>';
echo
$users[2]->name, ', ', $users[2]->birthday, '<br>';
echo
'<br>';

// Create an empty user and then delete it immediately
$user = new User();
$user->insert();
$user->delete();
?>
The DataObject class example
<?php
class DataObject {
private
$changedFields = array(); // list of updated fields
private $data = array(); // original row from PDOStatement
private $funcFields = array(); // fields that use MySQL functions
// The properties above are private in this class, so even if in your subclass you define some properties named the same, or you associate a property of the same name with a field in your table, they will never influence these properties.
function __get($property) {
if (isset(
$this::$_propertyList[$property])) {
return
$this->data[$this::$_propertyList[$property]]; // access fields by PHP properties
} else {
return
$this->$property; // throw the default PHP error
}
}
function
__set($property, $value) {
if (isset(
$this::$_propertyList[$property])) {
$field = $this::$_propertyList[$property];
$this->data[$field] = $value; // update $data

// take down changed fields
if (!in_array($field, $this->changedFields)) {
array_push($this->changedFields, $field);
}
$index = array_search($field, $this->funcFields);
if (
$index !== false) {
unset(
$this->funcFields[$index]);
$this->funcFields = array_values($this->funcFields);
}
} else {
// For fetchObject
$this->data[$property] = $value; // redirect to Array $data
}
}
private function
checkPrimaryKey() {}
private function
clear() {}
public function
delete() {}
public function
insert() {}
public function
update() {}
public function
useFunction($property, $function) {}
}
?>
dave at davidhbrown dot us
9 年前
如果使用命名空間的類別,您必須提供完整的類別名稱;fetchObject 似乎無法辨識任何「use」陳述式。

這會導致 PHP 致命錯誤:找不到類別 'MyClass'…
<?php
use MyNamespace\MyClass;
// ...
$o = $statement->fetchObject('MyClass'));
?>
這樣可以運作
<?php
use MyNamespace\MyClass; //我的程式碼仍然需要這個
// ...
$o = $statement->fetchObject('MyNamespace\\MyClass'));
?>
To Top