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

参见

添加备注

用户贡献的备注 8 个备注

107
rasmus at mindplay dot dk
11 年前
请注意 PDOStatement::fetchObject() 的非正统行为,它在调用构造函数之前注入属性值 - 换句话说,如果你的类在构造函数中将属性值初始化为默认值,你将覆盖 fetchObject() 注入的值!

在你的 __construct() 方法中使用 var_dump($this) 将揭示属性值在调用你的构造函数之前已被初始化,所以要小心。

出于这个原因,我强烈建议你手动重新填充你的对象,在将数据作为数组检索之后,而不是试图让 PDO 将属性直接应用到你的对象上。

显然有人认为他们在这里很聪明 - 允许你从构造函数访问重新填充的属性值。不幸的是,这不是 OOP 的工作方式 - 构造函数,按定义,是构造时调用的第一个方法。

如果你需要在对象构造和重新填充后初始化你的对象,我建议你的模型类型实现一个带有 init() 方法的接口,并且你的数据访问层在重新填充后调用此方法(如果已实现)。
25
Val Bancer
3 年前
如果你希望在 `fetchObject` 设置属性之前调用构造函数,则应使用带有 `PDO::FETCH_PROPS_LATE` 参数的 `PDOStatement::fetch` 方法。
15
beinghavingbreackfast at gmail dot com
9 年前
应该提到,此方法可以设置非公开属性。这听起来可能很奇怪,但它在基于 MySQL 结果创建对象时实际上非常有用。
考虑一个 User 类

<?php
class User {
// 私有属性
private $id, $name;

private function
__construct () {}

public static function
load_by_id ($id) {
$stmt = $pdo->prepare('SELECT id, name FROM users WHERE id=?');
$stmt->execute([$id]);
return
$stmt->fetchObject(__CLASS__);
}
/* 同样的方法可以用 "name" 列/属性编写 */
}

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

fetchObject() 不关心属性是公有的还是私有的。它只是将结果传递给对象。输出类似于

object(User)#3 (2) {
["id":"User":private]=>
string(1) "1"
["name":"User":private]=>
string(10) "John Smith"
}
8
sebastian dot rapetti at alice dot it
7 年前
PDOStatement::fetchObject() 将值注入为字符串,我需要一个转换类型。

我在类构造函数中包含 settype() 函数来实现这一点

以下方法通过 ID 查找用户并返回用户对象实例

<?php
class UserMapper extends MapperAbstract
{
// 其他代码
public function findById(int $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();

return
$pdos->fetchObject('\DomainObjects\User', array($this->password));
}
// 其他代码
}
?>

带有类型处理的 User 类

<?php
class User extends DomainObjectAbstract
{
// 其他代码
public function __construct(Password $password)
{
$this->passwordUtility = $password;

settype($this->objectId, 'integer');
settype($this->active, 'integer');
}
// 其他代码
}
?>

返回的 User 实例的 var_dump()

<?php
object
(DomainObjects\User)[18]
public
'name' => string 'root' (length=4)
public
'description' => string 'System User' (length=11)
public
'password' => string '$2y$11$4IAn6SRaB0osPz8afZC5D.CmTrBGxnb5FQEygPjDirK9SWE/u8YuO' (length=60)
public
'active' => int 1
public 'created' => string '2015-02-14 10:39:00' (length=19)
public
'lastUpdate' => string '2016-08-30 18:46:56' (length=19)
private
'passwordUtility' =>
object(Auth\Password)[13]
protected
'options' =>
array (
size=1)
'cost' => int 11
protected 'objectId' => int 1
?>

'objectId' 和 'active' 现在是必需的类型
3
zlk1214 at gmail dot com
8 年前
您可以以面向对象的方式访问 MySQL 表格。假设您有一个名为 Users 的表格,它包含以下字段:UserID、UserName、UserPassword、UserBirthday,您可以创建一个继承 DataObject 的 PHP 类并将其与该表格关联
<?php
class User extends DataObject {
// name: 表格名称,key: 主键(可以是数组),auto: AUTO_INCREMENT 字段
protected static $_table = array('name' => 'Users', 'key' => 'UserID', 'auto' => 'UserID');
// PHP 属性与 MySQL 字段名称之间的关系
protected static $_propertyList = array('id' => 'UserID', 'name' => 'UserName', 'password' => 'UserPassword', 'birthday' => 'UserBirthday');

// 获取所有用户作为数组的方法
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;
}
// 获取特定用户的方法
public static function GetUserByName($name) {}
public static function
GetUserByID($name) {}

// 当前用户对象的方法
public function checkPassword($password) {return $this->password == $password;}
public function
showLink() {return "<a href=\"user.php?i={$this->id}\">{$this->name}</a>";}
}

// 然后,您可以创建此类的实例以在您的表格中插入一行
$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>';

// 更新该行
$user->password = '112233';
$user->update();
} else {
echo
'INSERT Failed<br>';
}
// 通过查询获取特定用户
$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>';

// 通过类的静态方法获取所有用户
$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>';

// 创建一个空用户,然后立即将其删除
$user = new User();
$user->insert();
$user->delete();
?>
DataObject 类示例
<?php
class DataObject {
private
$changedFields = array(); // 更新的字段列表
private $data = array(); // PDOStatement 中的原始行
private $funcFields = array(); // 使用 MySQL 函数的字段
// 上述属性在这个类中是私有的,所以即使在你的子类中你定义了一些同名属性,或者你将同名属性与你表中的字段关联起来,它们都不会影响这些属性。
function __get($property) {
if (isset(
$this::$_propertyList[$property])) {
return
$this->data[$this::$_propertyList[$property]]; // 通过 PHP 属性访问字段
} else {
return
$this->$property; // 抛出默认的 PHP 错误
}
}
function
__set($property, $value) {
if (isset(
$this::$_propertyList[$property])) {
$field = $this::$_propertyList[$property];
$this->data[$field] = $value; // 更新 $data

// 记录变更字段
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 {
// 用于 fetchObject
$this->data[$property] = $value; // 重定向到数组 $data
}
}
private function
checkPrimaryKey() {}
private function
clear() {}
public function
delete() {}
public function
insert() {}
public function
update() {}
public function
useFunction($property, $function) {}
}
?>
2
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'));
?>
-15
Anonymous
9 年前
我认为我们可以使用这种变体来实现构造函数,这是我的例子

<?php
class User{
public
$user;
public
$password;
public
$name;
public
$email;

public function
__construct(){
$args = func_get_args();
$nargs = func_num_args();
$attribs = get_class_vars(get_class($this));
if(isset(
$args)){
foreach(
$args as $value){
$attrib = key($attribs);
$this->$attrib = $value;
next($attribs);
}
}
}
}
-34
Vegard Lkken
10 年前
由于在构造函数执行之前注入对象属性,我通常这样构建我的类,以确保已设置的属性不会被覆盖

<?php
class Person {
public
$name;
public
$age;
public
$sex;

public function
__construct($name=NULL, $age=NULL, $sex=NULL) {
$this->name = $name === NULL ? $this->name : $name;
$this->age = $age === NULL ? $this->age : $age;
$this->sex = $sex === NULL ? $this->sex : $sex;
}
}
?>
To Top