PDO将列拉入我的对象中,这些列未在我的类中定义

时间:2015-10-19 21:39:11

标签: php pdo

所以我定义了一个具有一些预定义属性的类。

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
    ...
)

因此...

  • 为什么要放入我没有定义的新属性?
  • 如何阻止它创建自己的属性?
  • 我做错了吗?
  • 即使制作我自己的类(模型)并声明属性,如果它只是想在其中放置任何想要的东西,目的是什么?

3 个答案:

答案 0 :(得分:3)

FETCH_CLASS

旨在将结果集的列映射到类中的命名属性。

如果您只想要一些属性,请更改您的查询并仅选择您需要的属性,即

SELECT id, firstName, lastName FROM users

答案 1 :(得分:1)

至于解释为什么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);
}    

我不知道使用这种方法是否会有任何附加值,而不仅仅是在查询中指定所需的列。您基本上只是将从查询中指定可能很长的列列表的工作转移到对象中。

答案 2 :(得分:0)

解决此问题的一种方法是检入构造函数中由类定义的var:

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。我使用了一个特质使该函数在多个类中可用,并且效果很好。然后,可以使用setFetchMode调用上的参数在构造函数中将其设置为可选:

$db->setFetchMode(PDO::FETCH_CLASS, 'User', [User::CLEAN]);

然后,您的构造函数可以如下所示:

public function __construct($type = null) {
    if ($type == self::CLEAN) {
        $this->clean();
    }
}

这显然不能与PDO :: FETCH_PROPS_LATE一起使用。