In PHP how can I access a “:private” array in an o

2019-01-18 23:01发布

问题:

Up until around 3.3beta1 items in the WP_Admin_Bar Object could be accessed using this type of syntax, for example to change the CSS class of one of the existing menu items:

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

When running print_r($wp_admin_bar) the output looked something like this:

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

However, around version 3.3beta2 the above syntax for changing a menu item's CSS class no longer works, and the output from print_r($wp_admin_bar) reveals a different structure for that object:

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

                )

I realize that Wordpress may not want me fiddling with the menus this way, and if there was a more standardized way to do this I would love to use it, but as far as I know there are only two functions that are available to modify the admin bar, add_menu_item and remove_menu_item, and these do not give the flexibility to do things like changing the attributes of existing menu items.

To confirm, I looked at wp-includes/class-wp-admin-bar.php it is clear that Wordpress has changed the way they define the variables.

Old Class

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

New Class

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

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

So my question is if I have access to the global $wp_admin_bar object, is there I way I can access the objects inside nodes:WP_Admin_Bar:private? And if not, is there another way to get to these objects, such as creating a new class that extends the WP_Admin_Bar class and then accessing the objects from there?

ps: I'm trying to overcome this challenge without changing the core Wordpress files...

Link to the file: http://phpxref.ftwr.co.uk/wordpress/nav.html?wp-includes/class-wp-admin-bar.php.source.html

回答1:

Change them to protected member variables and extend the class.

Whoever wrote the class with private members effectively made the class "final". Which goes to show that you should always write your members as protected, unless there's a really, REALLY good reason to do otherwise.

Hope that helps...



回答2:

If you dont want to touch the core files, then you have to use Reflection:

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

The hackish alternative would be casting the object to array and then doing:

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


回答3:

If I understand correctly your question, you're asking if you can access an object's private variables, but I guess you know you can't unless there's a method for it in the class, so this may be a trivial non-useful answer, but just in case:

Look at the class' code. Does it have any method to retrieve those variables, like get_nodes(),get_root(), etc? If not you have 3 alternatives: recode the class set the vars public, recode the class and add the methods, or recode the class and set the variables protected, then create a new class extending the parent one with those methods (I recomend this one, since it has less impact on the parent class).

Anyway if you can't recode the class and it has no get methods you won't be able to access those private variables.