Определить, является ли свойство объекта закрытым в PHP

Я пытаюсь создать объект PHP (5), который может выполнять итерацию по своим свойствам, создавая SQL-запрос только на основе его общедоступных свойств, а не частных.

Поскольку этот метод родительского объекта должен использоваться дочерними объектами, я не могу просто пропустить частные свойства по имени (я не буду знать, что они есть в дочерних объектах).

Есть ли простой способ определить изнутри объекта, какие из его свойств являются частными?

Вот упрощенный пример того, что у меня есть до сих пор, но этот вывод включает значение $bar:

class testClass {

    public $foo = 'foo';
    public $fee = 'fee';
    public $fum = 'fum';

    private $bar = 'bar';

    function makeString()
    {
        $string = "";

        foreach($this as $field => $val) {

            $string.= " property '".$field."' = '".$val."' <br/>";

        }

        return $string;
    }

}

$test = new testClass();
echo $test->makeString();

Дает вывод:

property 'foo' = 'foo'
property 'fee' = 'fee'
property 'fum' = 'fum'
property 'bar' = 'bar' 

Я бы хотел, чтобы это не включало «бар».

Если есть лучший способ выполнить итерацию только по общедоступным свойствам объекта, он будет работать и здесь.


person Hippyjim    schedule 12.05.2010    source источник


Ответы (7)


Вы можете использовать Reflection для изучения свойств класса. Чтобы получить только общедоступные и защищенные свойства, профилируйте подходящий фильтр для метода ReflectionClass::getProperties.

Вот быстрый пример использования вашего метода makeString.

public function makeString()
{
    $string = "";
    $reflection = new ReflectionObject($this);
    $properties = $reflection->getProperties(ReflectionProperty::IS_PUBLIC);
    foreach ($properties as $property) {
        $name    = $property->getName();
        $value   = $property->getValue($this);
        $string .= sprintf(" property '%s' = '%s' <br/>", $name, $value);
    }
    return $string;
}
person salathe    schedule 12.05.2010
comment
Спасибо - я думаю, что powtac опередил вас примерно на 30 секунд, но да, это работает именно так, как нужно. - person Hippyjim; 12.05.2010
comment
Да, я думаю, слишком много времени было потрачено на создание красивого ответа с аккуратными и аккуратными ссылками на документы. Урок усвоен, быстрые и грязные ответы с этого момента! :-) - person salathe; 12.05.2010

Проверьте этот код на http://php.net/manual/reflectionclass.getproperties.php#93984

  public function listProperties() {
    $reflect = new ReflectionObject($this);
    foreach ($reflect->getProperties(ReflectionProperty::IS_PUBLIC /* + ReflectionProperty::IS_PROTECTED*/) as $prop) {
      print $prop->getName() . "\n";
    }
  }
person powtac    schedule 12.05.2010
comment
Это именно то, что мне было нужно. Спасибо за урок! - person Hippyjim; 12.05.2010

Более быстрое решение, которое я нашел:

class Extras
{
    public static function get_vars($obj)
    {
        return get_object_vars($obj);
    }
}

а затем вызовите внутри вашего testClass:

$vars = Extras::get_vars($this);

дополнительное чтение на PHP.net

person jweatherby    schedule 20.11.2012

Если вы приведете объект к массиву перед его итерацией, закрытые и защищенные члены будут иметь специальные префиксы:

class Test{
  public $a = 1;
  private $b = 1;
  protected $c = 1;
}
$a = new Test();
var_dump((array) $a);

отображает это:

array(3) {
  ["a"]=>
  int(1)
  ["Testb"]=>
  int(1)
  ["*c"]=>
  int(1)
}

Там тоже есть скрытые символы, которые не отображаются. Но вы можете написать код для их обнаружения. Например, регулярному выражению /\0\*\0(.*)$/ будут соответствовать защищенные ключи, а /\0.*\0(.*)$/ — закрытые. В обоих случаях первая группа захвата соответствует имени участника.

person JW.    schedule 12.05.2010

Вы можете использовать массив для хранения общедоступных свойств, добавить метод-оболочку и использовать массив для вставки данных в SQL.

person Piotr Pankowski    schedule 12.05.2010

Вы можете легко использовать Reflection API для проверки видимости свойств:

$rp = new \ReflectionProperty($object, $property);
if ($rp->isPrivate) {
  // Do if the property is private
} else {
  // Do if the property is public or protected
}
person Milad Rahimi    schedule 16.04.2015

person    schedule
comment
Также есть класс отражения и магический метод __get(). - person powtac; 12.05.2010
comment
Боюсь, я ничего не знаю о классе отражения - мне нужно будет немного погуглить. Спасибо за указатель. - person Hippyjim; 12.05.2010
comment
Раньше я тоже игнорировал его, но потом понял, какие большие возможности у вас могут быть с ним. - person powtac; 12.05.2010
comment
еще один инструмент в наборе инструментов - person Louis Loudog Trottier; 09.01.2017