Обнаруживать, если свойство объекта является приватным в 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'
Я бы хотел, чтобы он не включал "bar".
Если есть лучший способ повторить только публичные свойства объекта, это тоже сработает.
Ответы
Ответ 1
Вы можете использовать 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;
}
Ответ 2
Проверьте этот код 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";
}
}
Ответ 3
Более быстрое решение, которое я нашел:
class Extras
{
public static function get_vars($obj)
{
return get_object_vars($obj);
}
}
а затем вызовите внутри вашего testClass:
$vars = Extras::get_vars($this);
дополнительное чтение в PHP.net
Ответ 4
Если вы передадите объект массиву перед его итерацией, частные и защищенные члены будут иметь специальные префиксы:
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(.*)$/
будет соответствовать частным. В обоих случаях первая группа захвата соответствует имени члена.
Ответ 5
foreach (get_class_vars(get_class($this)) ....
Ответ 6
Вы можете использовать массив для хранения общедоступных свойств, добавить некоторый метод-оболочку и использовать массив для вставки данных в SQL.
Ответ 7
Вы можете использовать Reflection API для проверки видимости свойств:
$rp = new \ReflectionProperty($object,$property);
if($rp->isPrivate) {
// Run if the property is private
} else {
// Run if the property is Public or Protected
}