Подтвердить что ты не робот

Как получить защищенное свойство объекта в PHP

У меня есть объект, имеющий некоторое защищенное свойство, которое я хочу получить и установить. Объект выглядит как

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
)

Я хочу получить свойство value объекта. Когда я пытаюсь $obj->_value или $obj->value, он генерирует ошибку. Я искал и нашел решение использовать PHP Reflection Class. Он работал на моем локальном, но на сервере PHP версии 5.2.17 Поэтому я не могу использовать эту функцию там. Итак, любое решение, как получить такое свойство?

4b9b3361

Ответ 1

То, для чего предназначен "защищенный", как гласит глава Visibility:

Объявленные защищенные члены могут быть доступны только внутри самого класса и наследуемых и родительских классов.

Если вам нужно получить доступ к свойству снаружи, выберите один из них:

  • Не объявляйте его защищенным, сделайте его общедоступным
  • Напишите пару функций для получения и установки значения (геттеры и сеттеры)

Если вы не хотите изменять исходный класс (потому что это сторонняя библиотека, которую вы не хотите испортить), создайте собственный класс, который расширяет исходный:

class MyFields_Form_Element_Location extends Fields_Form_Element_Location{
}

... и добавьте там свой приемник/сеттер.

Ответ 2

Вот действительно простой пример (без проверки ошибок) использования ReflectionClass:

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

Я знаю, что вы сказали, что ограничены 5.2, но это было 2 года назад, 5.5 - самая старая поддерживаемая версия, и я надеюсь помочь людям с современными версии.

Ответ 3

Объект может быть типизирован в (ассоциативный) массив, а защищенные члены имеют ключи с префиксом chr(0).'*'.chr(0) (см. @fardelian comment здесь). Используя эту непризнанную функцию, вы можете написать "exposer":

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

В качестве альтернативы вы можете проанализировать значение из serialized string, где (кажется) защищенные члены имеют один и тот же префикс (надеюсь, что php 5.2 не изменил его).

Ответ 4

Если вы не можете изменить исходный класс и расширить его, это также не вариант, вы можете использовать интерфейс ReflectionProperty.

Библиотека phptoolcase имеет для этого удобный способ:

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

Статическое свойство из одноэлементного класса:

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

Вы можете найти инструмент здесь: http://phptoolcase.com/guides/ptc-hm-guide.html

Ответ 5

Если вы хотите возиться с классом без добавления геттеров и сеттеров....

PHP 7 добавляет метод вызова ($ obj) (быстрее, чем старый bindTo) на замыканиях, позволяя вам вызывать функцию, поэтому переменная $this будет действовать так же, как и в классе - с полными разрешениями.

 //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 

Ответ 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']));