2014-01-22 4 views
0

Если у вас есть следующий код:Динамически добавить частные свойства объекта

<?php 

class Foo { public $attribute; } 

$o = new Foo(); 
$o->bar = true; 

?> 

PHP автоматически создает динамичную общественную собственность к этому объекту.

Есть ли возможность добавить динамические частные свойства? Или настроить их для приватного во время выполнения с помощью Reflection?

Мой метод __set нужно вызывать каждый раз, когда кто-то пытается установить какой-либо атрибут в моем классе. Я могу настроить все свои атрибуты на личную, но у меня есть атрибуты, которые динамически добавляются в этот класс, и когда атрибут добавляется автоматически, он имеет общедоступную видимость.

Это предотвращает вызов метода __set. Как я могу сделать динамические свойства при вызове значения __set?

На самом деле существует метод класса ReflectionProperty с именем setAccessible(). Я бы сделал противоположное этому методу.

+0

Короткий ответ, нет. Длинный ответ, возможно, вы сможете использовать отражение, чтобы изменить область действия свойства. Но отражение не должно использоваться так, как если бы вы не проводили отладку или модульное тестирование. –

+0

Какого черта вы пытаетесь сделать в любом случае? –

+0

@FabienWarniez только что добавил реальную информацию к вопросу. –

ответ

3

Это не представляется возможным в текущих версиях PHP.

В то время как ReflectionProperty::setAccessible()делает принимает логический аргумент, изменение, которое оно делает, позволяет только самому отражению получить доступ/не получить доступ к значению. Это фактически не изменяет доступность фактического имущества.

Как хакерское обходное решение, чтобы сохранить динамические свойства приватными, рассмотрите наличие свойств магазина __set, которые на самом деле не существуют в выделенном частном массиве. Пример код:

class Test { 

    private $foo; 
    public $bar; 
    private $_properties; 

    public function __get($prop) { 
     if(property_exists($this, $prop)) 
      return $this->$prop; 
     if(array_key_exists($prop, $this->_properties)) 
      return $this->_properties[$prop]; 
    } 

    public function __set($prop, $value) { 
     if(!property_exists($this, $prop)) { 
      $this->_properties[$prop] = $value; 
      echo 'SetDynamic: ', $prop, "\n"; 
      return; 
     } 
     $this->$prop = $value; 
     echo 'Set: ', $prop, "\n"; 
    } 

} 

Запуск от PHP интерактивного режима:

 
php > $t = new Test; 
php > $t->foo = 1; 
Set: foo 
php > $t->foo = 2; 
Set: foo 
php > $t->bar = 1; 
php > $t->testorama = 1; 
SetDynamic: testorama 
php > $t->testorama = 2; 
SetDynamic: testorama 

Хотя это будет гарантировать, что внешнего доступ всегда проходит через ваши __get и __set методов, она представляет собой проблему для внутреннего так как теперь вам всегда дают два места для проверки динамических свойств. Вот почему это хакерское решение вместо реального решения.

+0

Хотя это не может быть лучшим решением, это работало именно так, как мне было нужно. Я не могу вызывать эти атрибуты непосредственно внутри класса, они используются только извне и не доступны из класса. Кроме того, теперь я вижу, что я неправильно понял понятие метода setAccessible(). Благодаря! –

Смежные вопросы