PHP/MongoDB JSON 编码 - 调用 json_encode() 时无法访问内部类的私有变量

发布于 2024-12-23 08:11:19 字数 717 浏览 0 评论 0原文

所以基本上,我试图对我拥有的 php 类对象进行编码,并将其直接插入到 MongoDB 中。问题是,我的类有一个数组变量,用于保存该类的先前版本,因此这些私有变量无法通过 JSON 编码访问。我该如何解决这个问题?下面是我的类如何设置的一个示例(它更大,但这应该可以帮助您理解)

class App {
    private $version_number = "1.0.1";
    private $previous_versions= array(); //each element in the array will be a previous version of the App object 

    public function storeOldVersions(){
        $clone = clone $this;
        array_unshift($this->previous_versions, $clone);
    }
}

所以我做了类似的事情:

$app = new App();
$app->storeOldVersions();
echo json_encode($app);

json_encode 的回显正确显示了 $app 对象的数据,但 $previous_version 数组的json 编码为空,因为它的变量是私有的。如何解决这个问题,而不公开每个应用程序对象的变量?

谢谢!

So basically, I am trying to encode a php class object I have, and insert it directly into MongoDB. Problem is, my class has an array variable meant to hold previous versions of the class, so those private variables can't be accessed by JSON encode. How can I get around this? An example of how my class is set up is below (it's much bigger, but this should help you get the idea)

class App {
    private $version_number = "1.0.1";
    private $previous_versions= array(); //each element in the array will be a previous version of the App object 

    public function storeOldVersions(){
        $clone = clone $this;
        array_unshift($this->previous_versions, $clone);
    }
}

So I do something like:

$app = new App();
$app->storeOldVersions();
echo json_encode($app);

And the echo of the json_encode correct shows the $app object's data, but the $previous_version array's json encoding is blank because its variables are private. How can I fix this, without making each app object's variables public?

Thanks!

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

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

发布评论

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

评论(2

折戟 2024-12-30 08:11:19

您可以尝试添加一个公共 getter 来返回 previous_versions 数组:

public function getPreviousVersions()
{
    return $this->previous_versions;
}

-- 编辑 --

我阅读了 json_encode 的 php 文档,看起来有人遇到了与您相同的问题。查看https://www.php.net/json_encode,通过“搜索代码提交” mic dot sumner at gmail dot com”于 2010 年 7 月 2 日 01:39,看起来他想出了一个自定义解决方案,使私有成员在 json_encode 调用后可用。

You can try adding a public getter to return the previous_versions array:

public function getPreviousVersions()
{
    return $this->previous_versions;
}

-- Edit --

I read up on the php docs for json_encode, it looks like someone came across the same issue you have. Check out https://www.php.net/json_encode, and search for the code submission by "mic dot sumner at gmail dot com" on 02-Jul-2010 01:39, it looks like he came up with a custom solution to make private members available after a json_encode call.

爱格式化 2024-12-30 08:11:19

如果您希望允许 json_encode 访问私有受保护成员,您需要首先公开它们。您可以在某种辅助函数中执行此操作。用法:

$app = new App();

echo json_encode_private($app), "\n";

然后可以像这样输出:

{"_App_version_number":"1.0.1","_App_previous_versions":{}}

这个版本的函数非常简单,它利用 PHP 中的一个简单功能使私有和受保护的成员可见:

/**
 * json_encode object including private and protected members
 * 
 * @param object $object
 * @return string JSON
 */
function json_encode_private($object)
{
    if (!is_object($object))
        throw new InvalidArgumentException('Object type mismatch.');

    $json = json_encode((array) $object, JSON_FORCE_OBJECT);
    $json = preg_replace('~([{,]")\\\\u0000(\w+)\\\\u0000~i', '$1_$2_', $json);
    $json = preg_replace('~([{,]")\\\\u0000(\*)\\\\u0000~i', '$1_', $json);

    return $json;
}

它使用正则表达式,我只是有另一个想法,但是我需要先测试一下。希望这有帮助。

编辑:它是如何工作的?

转换为数组 (array) 将使私有属性可用于 json_encode。由于它现在是一个数组,JSON_FORCE_OBJECT 将再次生成 json 以将其编码为对象。

正则表达式用于重新命名私有和受保护的属性,因为它们包含特殊的 NUL 字节标记,如果您想在 JavaScript 中加载对象,这些标记并不方便。

由于它只是一个正则表达式而不是 json 解析器,因此属性内的类似格式数据也会发生更改,但我认为通常情况并非如此。但请注意。

另外请注意,此版本不适用于递归复杂对象。

应该可以基于 PHP 的 ReflectionDocs 进行扩展 能力。这还允许过滤特定成员或访问类型,以及定义如何命名这些成员的更详细方案。

If you want to allow json_encode to access private or protected members you need to expose them first. You can do this inside some sort of helper function. Usage:

$app = new App();

echo json_encode_private($app), "\n";

Which could then output like so:

{"_App_version_number":"1.0.1","_App_previous_versions":{}}

This version of such a function is pretty bare, it makes use of a simple feature in PHP to make private and protected members visible:

/**
 * json_encode object including private and protected members
 * 
 * @param object $object
 * @return string JSON
 */
function json_encode_private($object)
{
    if (!is_object($object))
        throw new InvalidArgumentException('Object type mismatch.');

    $json = json_encode((array) $object, JSON_FORCE_OBJECT);
    $json = preg_replace('~([{,]")\\\\u0000(\w+)\\\\u0000~i', '$1_$2_', $json);
    $json = preg_replace('~([{,]")\\\\u0000(\*)\\\\u0000~i', '$1_', $json);

    return $json;
}

It's making use of a regular expression, I just have another idea but I need to test it first. Hope this is helpful.

Edit: How does it work?

The cast to array (array) will make the private properties available to json_encode. As it's now an array, JSON_FORCE_OBJECT will make the json again to encode it as an object.

The regular expressions are used to re-name the private and protected properties as they contain special NUL byte markers which aren't handy if you want to load the object in javascript.

As it's only a regular expression and not a json parser, similar formatted data inside properties will get changed, too, but I assume this is most often not the case. But be warned.

Additionally take notice that this doesn't work for complex objects recursively with this version.

It should be possible to extend this based on PHP's Reflection­Docs capabilities. This would also allow to filter specific members or access types as well as to define a more detailed scheme how these members should be named.

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