从单个PDO阵列实例化多个PHP对象(无需样板)

如果您想从数据库中获取单个对象,PDO非常有用:

$obj = $handle->fetchAll(PDO::FETCH_CLASS, $obj_name);

如果您希望在一行中返回多个类类型(例如:在进行JOIN时),则PDO不太有用:

$handle->fetchAll(PDO::FETCH_ASSOC);

…followed by some data mapping on the resulting array.很好 – 除了我想出来的每一种方法看起来都很糟糕.

我的问题是:当数组的内容可能反映所有,没有,某些或多于类所需的内容时,如何以优雅,健壮的方式从同一数组中实例化多个对象?

例:

给定PDO从数据库返回的数组$vars =(‘a’=> 1,’b’=> 2,’c’=> 3,’x’=> 7,’y’=> ; 8,’z’=> 9),构造对象ABC(需要$a,$b和$c)和XYZ($x,$y,$z),而不需要太多的复制和粘贴.

选项1

class ABC {
    private $a, $b, $c;
    function __construct ($a = null, $b = null, $c = null) {
        $this->$a = $a ? $a : $this->a;
        $this->$b = $b ? $b : $this->b;
        ...

(许多样板代码/复制粘贴/要求实例化代码已按正确顺序准备好所有变量)

选项2

function ABCFactory($vars = array()) {
    return new ABC($vars['a'], $vars['b']....

(更好,但如果$vars中不存在数组键,则会抱怨.当然,我们可以使用isset()但这会使样板问题更严重)

选项3

foreach ($vars AS $key => $value) {
    eval("if (isset(\$key) && \$value) \$this->$key = '$value';");
}

(它有效,它很整洁,它很整洁,它很容易重复使用,它会反映我添加的任何新类变量……但它是eval(),这让我做噩梦!:])

dockeryZ暗示了它,但mleko提供了答案.我之前没有听说过变量变量,但它们正是我想要的.我终于去了:

$def_vars = get_object_vars($this);
foreach ($vars AS $key => $value) {
    if (array_key_exists($key, $def_vars)) $this->{$key}=$value;
}

但是,任何在将来发现这一点的人都应该记住Johan Perez的答案,而不是使用这个片段作为构造函数中的快捷方式…特别是如果输入数组来自用户的GET或POST参数!

最佳答案 干得好

<?php
class Name {
    public function __construct($data) {
        foreach($data as $key=>$val){
            $this->{$key}=$val;
        }

    }
}
点赞