Jak uzyskać chronioną właściwość obiektu w PHP

Mam obiekt posiadający jakąś chronioną własność, którą chcę zdobyć i ustawić. Obiekt wygląda jak

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
)

Chcę uzyskać value właściwość obiektu. Kiedy próbuję $obj->_value lub $obj->value generuje błąd. Szukałem i znalazłem rozwiązanie do użycia PHP Reflection Class. Działa na moim lokalnym, ale na serwerze wersja PHP jest 5.2.17, więc nie mogę tam korzystać z tej funkcji. Więc jakieś rozwiązanie, jak uzyskać taką nieruchomość?

Author: Jan Turoň, 2013-12-02

6 answers

Po to jest "chronione" , jak wyjaśnia Rozdział Visibility :

Członkowie zadeklarowani jako protected mogą być dostępni tylko wewnątrz samej klasy oraz przez klasy dziedziczone i nadrzędne.

Jeśli chcesz uzyskać dostęp do nieruchomości z zewnątrz, wybierz jedną z nich:

  • nie deklaruj jej jako chronionej, zamiast tego upublicznij ją
  • napisz kilka funkcji do get i ustaw wartość (getters i setters)

Jeśli nie chcesz zmodyfikuj oryginalną klasę (ponieważ jest to biblioteka innej firmy, której nie chcesz bałagan) Utwórz klasę niestandardową, która rozszerza oryginalną:

class MyFields_Form_Element_Location extends Fields_Form_Element_Location{
}

... i dodaj tam swój getter / setter.

 16
Author: Álvaro González,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-02 17:57:17

Oto bardzo prosty przykład (bez sprawdzania błędów) jak używać ReflectionClass:

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

Wiem, że mówiłeś, że ograniczyłeś się do 5.2, ale to było 2 lata temu, 5.5 jest najstarszą obsługiwaną wersją i mam nadzieję pomóc ludziom z nowoczesnymi wersjami.

 65
Author: drewish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-10 14:01:23

Obiekt może być wpisany do tablicy asocjacyjnej, a chronione elementy mają klucze prefiksowe chr(0).'*'.chr(0) (Zobacz komentarz @fardelian tutaj). Korzystając z tej nieudokumentowanej funkcji można napisać "exposer":

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

Alternatywnie, możesz przetworzyć wartość z serialized string, gdzie (jak się wydaje) protected members mają ten sam prefiks(mam nadzieję, że php 5.2 tego nie zmieniło).

 36
Author: Jan Turoň,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-03 11:09:55

Jeśli chcesz majstrować z klasą bez dodawania getterów i setterów....

PHP 7 dodaje metodę call ($obj) (szybszą niż stare bindTo) na closures pozwalającą na wywołanie funkcji, dzięki czemu zmienna $this będzie działać tak, jak w klasie-z pełnymi uprawnieniami.

 //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 
 7
Author: user2782001,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-05 04:13:55

Jeśli nie możesz zmodyfikować oryginalnej klasy, a jej rozszerzenie również nie jest opcją, możesz użyć interfejsu ReflectionProperty.

Biblioteka phptoolcase ma do tego przydatną metodę:

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

Własność statyczna z klasy singleton:

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

Narzędzie znajdziesz tutaj: http://phptoolcase.com/guides/ptc-hm-guide.html

 3
Author: Charlie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-09 07:38:22
  $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']));
 -1
Author: stephen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-08 14:03:50