我可以制作PDOStatement-> fetchObject不使用非成员变量吗?

时间:2010-05-29 00:41:28

标签: php pdo

假设我有一个这样的课程:

Class User {
  var $id
  var $name;
}

我在php中使用PDO运行查询,如下所示:

$stm = $db->prepare('select * from users where id = :id');
$r = $stm->execute(array(':id' => $id));
$user = $r->fetchObject('User');

如果我vardump我的用户对象,它有各种其他字段,我没有在User类中定义。显然,我可以使我的查询具体,以便它只返回我需要/想要的字段。但是,如果我不想这样做,有什么方法可以按照我想要的方式进行这项工作吗?

我喜欢fetchObject的想法,因为它是一行代码来创建这个对象并为我设置成员变量。我只是不希望它设置我在课堂上没有定义的变量。

编辑:

好像karim79似乎是正确的,fetch或fetchObject将无法按照我想要的方式工作。在我进行获取后,我添加了以下一些代码来获得所需的结果。

$valid_vars = get_class_vars('User');
foreach (get_object_vars($user) as $key => $value) {
    if (!array_key_exists($key, $valid_vars)) {
        unset($user->$key);
    }
}

显然不是最优雅的解决方案:/我将扩展PDOStatement类并添加我自己的方法fetchIntoObject或类似的东西,并自动执行这些取消设置。希望不应该有太大的开销,但我希望能够轻松地通过1行代码获取对象:)

SUPER EDIT:

感谢mamaar的评论,我又回到了文档。我发现了问题所在。 http://us.php.net/manual/en/pdo.constants.php并向下滚动到PDO :: FETCH_CLASS,它解释了如果类中不存在属性,则使用魔术方法__set()。我覆盖了我的目标类中的方法和tada,工作。再次,不是最优雅的解决方案。但现在我明白了为什么,这对我很重要:D

4 个答案:

答案 0 :(得分:2)

PDOStatement->execute()不返回对象 - 它返回TRUE / FALSE。

将第2行和第3行更改为

if ( $stm->execute( array( ':id' => $id ) ) ){    
    $user = $stm->fetchObject( 'User' );
}

并且有效

答案 1 :(得分:1)

我认为这不可行。 fetchObject将创建一个指定为fetchObject的{​​{1}}参数的类名实例(默认为stdClass)。它不会检查具有相同名称的现有类并创建实例,仅将值分配给与结果中的列名匹配的成员变量。我建议依靠更无聊的东西,比如:

$class_name

这当然意味着为您的User类提供构造函数:

$user = new User($result['id'], $result['name']);

答案 2 :(得分:1)

您可以将PDO :: FETCH_CLASS或PDO :: FETCH_INTO的PDOStatement-> fetch方法用作$ fetch_style参数

编辑:所以我尝试过自己,并让它与PDOStatement->setFetchMode

一起使用
class User
{
    public $id;
    public $name;
}

$db = new PDO('mysql:host=127.0.0.1;dbname=test', 'username', 'password');

$stmt = $db->prepare("select * from users where id=:userId");
$stmt->setFetchMode(PDO::FETCH_CLASS, 'User');
$stmt->execute(array(':userId' => 1));

$user = $stmt->fetch();
var_dump($user);

答案 3 :(得分:0)

作为替代方案,您当然可以只获取一个数组并自行对其进行类型转换:

$user = (User) $r->fetch();
是的,我没见过这种行为。也许您激活了PDO :: FETCH_LAZY,这可能会创建额外的数据。您可以使用 - > fetchObject(“stdClass”)测试它,否则原因在于您的User类或其父级?