Защищенные свойства OO PHP недоступны в цикле foreach?

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

Я передаю объект статической функции в классе проверки, из другого класса (в данном случае User)

function validate() { $errors = Validation::validate($this); } 

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

 function validate($object) { $validation = new Validation(); print_r($object); print_r('<br />'); foreach($object as $key => $val) { print_r($val); isset($val->maxlength) ? $validation->validateLengthNoMoreThan($val->value, $val->maxlength) : null; isset($val->minlength) ? $validation->validateLengthAtLeast($val->value, $val->minlength) : null; isset($val->required) && ($val->required == true) ? $validation->validateNotBlank($val->value) : null; } return $validation->errors; } 

Я печатаю значения внутри функции только для тестовых целей. То, что я не понимаю, – это то, почему объект печатает отлично за пределами цикла foreach, но если я попытаюсь получить доступ к значениям в цикле, ничего не отображается.

Это то, что отображается ВНЕШНИЙ цикл foreach:

 Пользовательский объект ( 
 [имя пользователя: protected] => Объект свойства ([значение] => aaa [maxlength] => 12 [minlength] => 3 [required] => 1) 
 [firstname: protected] = Объект свойства ([значение] => aaa [maxlength] => 12 [minlength] => 3 [required] => 1)
 [lastname: protected] = Объект свойства ([значение] => aaa [maxlength] => 12 [minlength] => 3 [required] => 1) 
 ) 

Класс проверки НЕ расширяет класс User, поэтому я понимаю, почему значения будут недоступны, а не почему они доступны вне цикла, но не внутри него.

Кроме того, что было бы лучшим способом провести проверку на защищенные / частные свойства?

Любые советы / советы будут очень признательны.

Благодарю.

Вы можете обойти эту проблему, запустив свойства внутри фактического объекта. Поэтому каждый объект должен иметь функцию validate (), которую вы можете применить с интерфейсом. Например:

 class MyClass implements Validator { $var1; $var2; public function validate(){ //required by Validator interface $validation = new Validation(); foreach($this as $k=>$v) { //run validations } return $validation->errors; } } 

Из документов ( http://us3.php.net/manual/en/language.oop5.visibility.php ):

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

и из http://us3.php.net/manual/en/function.print-r.php :

print_r (), var_dump () и var_export () также будут показывать защищенные и частные свойства объектов с PHP 5. Статические члены класса не будут показаны.

Просто потому, что print_r () может что-то печатать, не означает, что вы можете получить доступ к вашему коду. рассмотрите print_r (), var_dump () и var_export () как специальные функции.

Скотт Сондерс правильно указывает, что документы PHP говорят, что вы не можете этого сделать, но PHP предоставляет эту информацию об объекте через var_export .

Следовательно, вы можете злоупотреблять eval, чтобы получить атрибуты частного и защищенного объекта, например:

 function get_object_vars_all($obj) { $objArr = substr(str_replace(get_class($obj)."::__set_state(","",var_export($obj,true)),0,-1); eval("\$values = $objArr;"); return $values; } 

Вот быстрый пример …

 class Test { protected $protectedAttrib = "protectedVal"; private $privateAttrib = "privateVal"; public $publicAttrib = "publicVal"; } $test = new Test(); print_r(get_object_vars_all($test)); 

… выход ….

 Array ( [protectedAttrib] => protectedVal [privateAttrib] => privateVal [publicAttrib] => publicVal ) 

Вы действительно не должны этого делать, потому что это побеждает цель использования OO, но вы можете!

Кроме того, обратите внимание, что многим людям не нравится использовать eval по разным причинам, здесь обсуждается.

Используйте отражение объекта для доступа к защищенным или закрытым значениям:

 $refl = new ReflectionObject($object); $prop = $refl->getProperty('yourproperty'); $prop->setAccessible(true); $value = $prop->getValue($object); 

Такое же предупреждение, данное DespairTyre, относится к этому решению: есть причины, по которым свойства защищены или закрыты. Однако есть ситуации, когда вы не хотите изменять код определенного класса, но должны получить доступ к его свойствам …

Вы можете использовать функцию get_object_vars ():

  $vars = get_object_vars($obj); foreach ($vars as $field=>$value){ ... } 

Он хорошо работает с защищенными полями.

Если свойства объекта User защищены или приватны, то foreach не пройдет их. Это может объяснить, почему вы не можете получить к ним доступ в инструкции foreach.

Если это так, то это легко разрешимо с помощью интерфейса SPL ArrayIterator: http://www.php.net/manual/en/class.arrayiterator.php