所以我定义了一个具有一些预定义属性的类。
class User
{
public $id;
public $firstName;
public $lastName;
}
然后,我使用 PDO::FETCH_CLASS
查询数据库,将结果提取到上述 User
类的对象中。
$sql = "SELECT * FROM users";
$dbh = new PDO($dsn, $username, $password);
$stmt = $dbh->query($sql);
$users = $stmt->fetchAll(PDO::FETCH_CLASS, 'User');
foreach($users as $user)
{
print_r($user);
}
但是现在,当我迭代生成的User
对象时,它包含我在User
类中未定义的其他属性。
User Object
(
[id] => 1
[firstName] => Bruce
[lastName] => Wayne
[city] => Gotham
[residence] => Batcave
...
)
所以。。。
- 为什么要放入我没有定义的新属性?
- 如何防止它创建自己的属性?
- 我做错了什么吗?
- 即使创建自己的类(模型(并声明属性的目的是什么,如果它只是要把它想要的东西放在那里?
FETCH_CLASS
旨在将结果集的列映射到类中的命名属性。
如果您只需要一些属性,请更改查询并仅获取所需的属性,即
SELECT id, firstName, lastName FROM users
至于解释为什么FETCH_CLASS
这样工作,我真的帮不上什么忙。但这就是它的工作原理,你没有做错任何事。如果您希望能够仅使用SELECT * ...
并将结果获取到仅填充其定义属性的对象中,我认为PDO没有任何内置部分可以做到这一点。实现此目的的一种方法是为对象创建一个构造函数,该构造函数将使用数组中的值对其进行初始化,如下所示。
class User
{
public $id;
public $firstName;
public $lastName;
function __construct($record) {
foreach (get_object_vars($this) as $key => $value) {
if (isset($record[$key])) $this->$key = $record[$key];
}
}
}
然后,您可以改用FETCH_ASSOC
,并使用生成的数组创建对象。
while ($record = $stmt->fetch(PDO::FETCH_ASSOC, 'User')) {
$users[] = new User($record);
}
我不知道使用这种方法是否会有任何附加值,而不仅仅是指定查询中需要哪些列。您基本上只是将指定可能很长的列列表的工作从查询转移到对象中。
解决此问题的一种方法是在构造函数中检查该类定义了哪些变量:
foreach(get_object_vars($this) as $objVar => $val) {
$classKeys = array_keys(get_class_vars(self::class));
foreach(get_object_vars($this) as $objVar => $val) {
if (!in_array($objVar, $classKeys)) {
$this->$objVar = null;
}
}
}
您最终仍会在类上获得额外的属性,但它们都设置为 null。 我使用了一个 trait 使这个函数在几个类中可用,它运行良好。 然后,您可以使用 setFetchMode 调用上的参数在构造函数中使其成为可选:
$db->setFetchMode(PDO::FETCH_CLASS, 'User', [User::CLEAN]);
然后构造函数可以看起来像这样:
public function __construct($type = null) {
if ($type == self::CLEAN) {
$this->clean();
}
}
这显然不能与PDO::FETCH_PROPS_LATE一起使用。