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

发布于 2024-09-03 13:07:05 字数 1214 浏览 4 评论 0原文

假设我有一个这样的类:

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 行代码轻松获取对象:)

超级编辑:

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

Lets say I have a class like this:

Class User {
  var $id
  var $name;
}

And I run a query using PDO in php like so:

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

If I vardump my user object it has all kinds of other fields in it that I have not defined in the User class. Obviously I could make my query specific so that it only gives me back the fields I need/want. But if I don't want to do that is there any way to make this work the way I want it to?

I like the idea of fetchObject, because it's one line of code to create this object and set member variables for me. I just don't want it to set variables I haven't defined in my class.

EDIT:

Well it seems like karim79 is right and the fetch or fetchObject won't work the way I want it to. I've added the following bit of code after I do the fetch to get the desired results.

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

Obviously not the most elegant solution :/ I'm going to extend the PDOStatement class and add my own method fetchIntoObject or something like that and automatically do these unsets. Hopefully shouldn't be to much overhead, but I want to be able to easily fetch into an object with 1 line of code :)

SUPER EDIT:

Thanks to mamaar's comment I went back to the documentation again. I found what the problem is. http://us.php.net/manual/en/pdo.constants.php and scroll down to PDO::FETCH_CLASS and it explains that the magic method __set() is used if properties don't exist in the class. I overwrote the method in my target class and tada, works. Again, not the most elegant solution. But now I understand the WHY, and that's important to me :D

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦毁影碎の 2024-09-10 13:07:05

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

将第 2 行和第 3 行更改为

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

,它就可以工作了

PDOStatement->execute() does not return an object - it returns TRUE/FALSE.

Change lines 2 and 3 to

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

and it works

守望孤独 2024-09-10 13:07:05

我认为这是不可能的。 fetchObject 将创建指定为 fetchObject$class_name 参数(默认为 stdClass)的类名实例。它不会检查具有相同名称的现有类并创建实例,仅将值分配给与结果中的列名称匹配的成员变量。我建议依赖一些更无聊的东西,就像这样:

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

这当然意味着给你的 User 类一个构造函数:

Class User {
  var $id
  var $name;

  public function __construct($id, $name)
  {
     $this->id = $id;
     $this->name = $name;
  }

}

I don't think that's possible. fetchObject will create an instance of the classname specified as fetchObject's $class_name parameter (which defaults to stdClass). It will not check for existing classes with the same name and create an instance, assigning values only to member variables which match column names in the result. I would suggest relying on something more boring, like this:

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

Which would of course mean giving your User class a constructor:

Class User {
  var $id
  var $name;

  public function __construct($id, $name)
  {
     $this->id = $id;
     $this->name = $name;
  }

}
可是我不能没有你 2024-09-10 13:07:05

您可能可以使用 PDOStatement->fetch 方法与 PDO::FETCH_CLASS 或 PDO::FETCH_INTO 作为 $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);

You could probably use the PDOStatement->fetch method with PDO::FETCH_CLASS or PDO::FETCH_INTO as the $fetch_style parameter

Edit: So I've tried myself, and got it to work with 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);
兮子 2024-09-10 13:07:05

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

$user = (User) $r->fetch();

顺便说一句,我还没有看到这种行为。也许您激活了 PDO::FETCH_LAZY,这可能会创建额外的数据。您可以使用 ->fetchObject("stdClass") 进行测试,否则原因在于您的 User 类或其父类?

As alternative, you can of course just fetch an array and simply typecast this yourself:

$user = (User) $r->fetch();

Btw, I've not seen this behaviour. Maybe you have PDO::FETCH_LAZY activated, that might create extra data. You could test it with ->fetchObject("stdClass"), else the reason resides with your User class, or its Parent?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文