在 PHP 中,如何访问对象中的 ":private" 数组?

Posted

技术标签:

【中文标题】在 PHP 中,如何访问对象中的 ":private" 数组?【英文标题】:In PHP how can I access a ":private" array in an object? 【发布时间】:2012-01-07 09:04:38 【问题描述】:

直到 WP_Admin_Bar Object 中的大约 3.3beta1 项可以使用这种类型的语法进行访问,例如更改现有菜单项之一的 CSS 类:

$wp_admin_bar->menu->'wp-logo'['meta']['class'] = 'new-class';

运行print_r($wp_admin_bar) 时,输出如下所示:

WP_Admin_Bar Object
(
    [menu] => stdClass Object
        (
            [my-account] => Array
                (

但是,在版本 3.3beta2 附近,上述用于更改菜单项 CSS 类的语法不再有效,print_r($wp_admin_bar) 的输出显示该对象的不同结构:

WP_Admin_Bar Object
(
    [nodes:WP_Admin_Bar:private] => Array
        (
            [my-account] => stdClass Object
                (
                    [id] => my-account

                )

我意识到 Wordpress 可能不希望我以这种方式摆弄菜单,如果有更标准化的方式来做到这一点,我很乐意使用它,但据我所知,只有两个功能可用修改管理栏,add_menu_itemremove_menu_item,它们不能灵活地执行更改现有菜单项的属性等操作。

为了确认,我查看了wp-includes/class-wp-admin-bar.php,很明显 Wordpress 已经改变了他们定义变量的方式。

老班

class WP_Admin_Bar 
    var $menu;
    var $proto = 'http://';
    var $user;

新课程

class WP_Admin_Bar 
    private $nodes = array();
    private $root = array();

    public $proto = 'http://';
    public $user;

所以我的问题是,如果我可以访问global $wp_admin_bar 对象,有没有办法可以访问nodes:WP_Admin_Bar:private 中的对象?如果没有,是否还有其他方法可以获取这些对象,例如创建一个扩展 WP_Admin_Bar 类的新类,然后从那里访问这些对象?

ps:我正在尝试在不更改核心 Wordpress 文件的情况下克服这一挑战...

文件链接:http://phpxref.ftwr.co.uk/wordpress/nav.html?wp-includes/class-wp-admin-bar.php.source.html

【问题讨论】:

【参考方案1】:

如果我正确理解了您的问题,您是在询问是否可以访问对象的私有变量,但我想您知道除非类中有针对它的方法,否则您不能,所以这可能是一个微不足道的非有用的答案,但以防万一:

查看班级的代码。是否有任何方法可以检索这些变量,例如 get_nodes()、get_root() 等?如果没有,你有 3 种选择:重新编码类设置 vars public,重新编码类并添加方法,或重新编码类并将变量设置为受保护,然后使用这些方法创建一个扩展父类的新类(我推荐这个,因为它对父类的影响较小)。

无论如何,如果您无法重新编码该类并且它没有 get 方法,您将无法访问这些私有变量。

【讨论】:

你说得对,我在这里将 private 与 protected 混淆了,已编辑。【参考方案2】:

将它们更改为受保护的成员变量并扩展类。

使用私有成员编写课程的人有效地使课程“最终”。这表明您应该始终将您的成员写为受保护的,除非有非常非常好的理由不这样做。

希望对您有所帮助...

【讨论】:

添加了指向该类文件的链接。希望通过扩展它而不更改核心文件来克服这个问题。 您的问题看起来非常好。也许您可以在发布之前提交包含此问题链接的错误报告。他们可能愿意根据您的需要对其进行更改。 codex.wordpress.org/Reporting_Bugs 我认为这是最好的做法。谢谢。 core.trac.wordpress.org/ticket/19371【参考方案3】:

如果你不想接触核心文件,那么你必须使用Reflection

$adminBar = new WP_Admin_Bar();
$reflector = new ReflectionObject($adminBar);
$nodes = $reflector->getProperty('nodes');
$nodes->setAccessible(true);
print_r($nodes->getValue($adminBar));

hackish 的替代方法是将对象转换为数组,然后执行:

$adminbar = (array) new WP_Admin_Bar;
$nodes = $adminbar[chr(0) . 'WP_Admin_Bar' . chr(0) . 'nodes'];
print_r($nodes);

【讨论】:

我会尝试Reflection 看看是否可行。不确定我是否可以将其转换为数组,因为我需要反对该类仍然可以使用它,以便可以渲染它。感谢您的详细回答:) 这对我很有用。接受的答案不回答问题!有时,如果不侵入另一方的代码,您就无法更改对象…… 对于hackish版本,key可以不同,用dump找到,key是"\x00*\x00id",实际上chr(0)等价于\x00所以key是chr (0).'*'.chr(0).'id'

以上是关于在 PHP 中,如何访问对象中的 ":private" 数组?的主要内容,如果未能解决你的问题,请参考以下文章

PHP 如何读取Javascript 对象的值?

如何访问 PHP 中的 JSON 元素,如数组对象?

如何覆盖父对象的静态属性并让父对象访问 PHP 中的新值?

如何访问一级深层文件中的对象?

在js中如何取出json中的对象的值

如何从 C++ 中的“指向对象的指针”向量访问对象