当我在具有私有属性的对象上使用 json_encode() 时,它会返回空对象 [duplicate]

When I use json_encode() on the object with private properties, it returns empty object [duplicate]

提问人:Radek 提问时间:10/22/2023 最后编辑:Your Common SenseRadek 更新时间:10/23/2023 访问量:63

问:

从理论上讲,当使用类型时,它应该返回指定类的对象,并将表列中的值分配给类的属性,即使它们是私有的。如果类中没有属性,也没有指定任何函数,则应创建一个新的公共属性。PDO::FETCH_CLASS__set()

这是我的班级:

class Product
{
    private string $id;
    private string $name;
    private int $price;

    public function __set(string $name, $value): void
    {
    }

    public function __get(string $name) : void
    {
    }
    
    public function getId()
    {
        return $this->id;
    }
    
    public function setId($id): void
    {
        $this->id = $id;
    }
}

这是我从表中获取所有记录的方法:

public function getAll()
    {
        $sql = "SELECT * FROM $this->table";

        $statement = $this->conn->query($sql);
        return $statement->fetchAll(PDO::FETCH_CLASS, 'Product');
    }

这将返回一个空 Product 对象的数组,即使名称相同,也应该为现有属性分配值。当属性是公共的时,它起作用,但当它们是私有的或受保护的时,它不起作用。

我知道分配给私有财产是一种奇怪的行为,但它在互联网上有很好的记录,包括 php.net,这个功能最近有没有被删除?我在更新日志或堆栈上找不到有关它的任何信息。

如果此行为现在已被弃用,请您告诉我如何在不显式使用类的 setter 的情况下将信息从一个表中获取到不同的对象类中?

提前感谢您的帮助。

编辑:

感谢您的回答,我已经确定 PDO 确实正常工作,当我var_dump阵列时,它看起来不错:

    /home/wwwroot/app/src/ProductController.php:67:
array (size=9)
  0 => 
    object(Product)[7]
      private string 'id' => *uninitialized*
      private string 'name' => string 'Harry Potter' (length=12)
      private int 'price' => int 200
  1 => 
    object(Product)[8]
      private string 'id' => *uninitialized*
      private string 'name' => string 'War and Peace' (length=13)
      private int 'price' => int 2000

但是,当我在数组上使用 json_encode() 时,它只是显示空对象,所以我认为这是因为我需要为该函数提供 assoc 数组而不是对象数组?

php mysql pdo

评论

0赞 Nigel Ren 10/22/2023
你能给出你得到的结果的样本吗?
0赞 Your Common Sense 10/23/2023
无法确认。PHP PDO FETCH_CLASS 肯定会分配给私有类属性
0赞 Your Common Sense 10/23/2023
我认为你应该翻阅你的书,它解释了“私人”是什么意思......

答:

-2赞 suchislife 10/23/2023 #1

该问题可能是由于空 和 方法造成的,这些方法覆盖了 的默认行为。删除或注释掉这些神奇的方法,以允许 PDO 填充私有属性。__set()__get()PDO::FETCH_CLASS

class Product
{
    private string $id;
    private string $name;
    private int $price;

    // Remove or comment out these magic methods
    // public function __set(string $name, $value): void
    // {
    // }

    // public function __get(string $name) : void
    // {
    // }

    public function getId()
    {
        return $this->id;
    }

    public function setId($id): void
    {
        $this->id = $id;
    }
}

如果专门添加了 empty 和 方法来阻止动态属性创建,则 将无法填充私有或受保护的属性。请考虑使用 flag 来确保在分配属性之前调用构造函数。__set()__get()PDO::FETCH_CLASSPDO::FETCH_PROPS_LATE

public function getAll()
{
    $sql = "SELECT * FROM $this->table";
    $statement = $this->conn->query($sql);
    return $statement->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Product');
}

另外,请查看这个很棒的 PHP PDO 信息来源。真的很好读。

(唯一合适的)PDO教程来自 phpdelusions.net

评论

0赞 Your Common Sense 10/23/2023
可能?为什么不测试一下呢?
0赞 Radek 10/23/2023
嗨,感谢您的回答和教程链接,不幸的是,事实并非如此,我将这些方法留空以阻止将任何其他公共属性从表添加到对象。