How to get protected property of object in PHP

2020-01-22 13:24发布

问题:

I have a object having some protected property that I want to get and set. The object looks like

Fields_Form_Element_Location Object
(
[helper] => formText
[_allowEmpty:protected] => 1
[_autoInsertNotEmptyValidator:protected] => 1
[_belongsTo:protected] => 


[_description:protected] => 
[_disableLoadDefaultDecorators:protected] => 
[_errorMessages:protected] => Array
    (
    )

[_errors:protected] => Array
    (
    )
[_isErrorForced:protected] => 
[_label:protected] => Current City


[_value:protected] => 93399
[class] => field_container field_19 option_1 parent_1
)

I want to get value property of the object. When I try $obj->_value or $obj->value it generates error. I searched and found the solution to use PHP Reflection Class. It worked on my local but on server PHP version is 5.2.17 So I cannot use this function there. So any solution how to get such property?

回答1:

That's what "protected" is meant for, as the Visibility chapter explains:

Members declared protected can be accessed only within the class itself and by inherited and parent classes.

If you need to access the property from outside, pick one:

  • Don't declare it as protected, make it public instead
  • Write a couple of functions to get and set the value (getters and setters)

If you don't want to modify the original class (because it's a third-party library you don't want to mess) create a custom class that extends the original one:

class MyFields_Form_Element_Location extends Fields_Form_Element_Location{
}

... and add your getter/setter there.



回答2:

Here's the really simple example (with no error checking) of how to use ReflectionClass:

function accessProtected($obj, $prop) {
  $reflection = new ReflectionClass($obj);
  $property = $reflection->getProperty($prop);
  $property->setAccessible(true);
  return $property->getValue($obj);
}

I know you said you were limited to 5.2, but that was 2 years ago, 5.5 is the oldest supported version and I'm hoping to help people with modern versions.



回答3:

Object can be typecasted into (associative) array and the protected members have keys prefixed with chr(0).'*'.chr(0) (see @fardelian's comment here). Using this undocummented feature you can write an "exposer":

function getProtectedValue($obj,$name) {
  $array = (array)$obj;
  $prefix = chr(0).'*'.chr(0);
  return $array[$prefix.$name];
}

Alternatively, you can parse the value from serialized string, where (it seems) protected members have the same prefix (I hope php 5.2 didn't change it).



回答4:

If you want to tinker with a class without adding getters and setters....

PHP 7 adds a call($obj) method (faster than old bindTo) on closures allowing you to call a function so the $this variable will act just as it would within a class -with full permissions.

 //test class with restricted properties
 class test{
    protected $bar="protected bar";
    private $foo="private foo";
    public function printProperties(){
        echo $this->bar."::".$this->foo;   
     }
 }

$testInstance=new test();
//we can change or read the restricted properties by doing this...
$change=function(){
    $this->bar="I changed bar";
    $this->foo="I changed foo";
};
$change->call($testInstance);
$testInstance->printProperties();
//outputs I changed bar::I changed foo in php 7.0 


回答5:

If you cannot modify the original class and extending it is not an option either, you can use the ReflectionProperty interface.

The phptoolcase library has a handy method for this:

$value = PtcHandyMan::getProperty( $your_object , ‘propertyName’);

Static property from a singleton class:

$value = PtcHandyMan::getProperty( ‘myCLassName’ , ‘propertyName’);

You can find the tool here: http://phptoolcase.com/guides/ptc-hm-guide.html



回答6:

  $propGetter = Closure::bind(  function($prop){return $this->$prop;}, $element['field_text']['#object'], $element['field_text']['#object'] );
  drupal_set_message('count='.count($propGetter('hostEntity')->field_captioned_carousel['und']));