OO PHP защищенные свойства не доступны в цикле foreach? - PullRequest
3 голосов
/ 29 октября 2009

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

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

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:

User Object ( 
[username:protected] => Property Object ( [value] => aaa [maxlength] => 12 [minlength] => 3 [required] => 1 ) 
[firstname:protected] =Property Object ( [value] => aaa [maxlength] => 12 [minlength] => 3 [required] => 1 )
[lastname:protected] =Property Object ( [value] => aaa [maxlength] => 12 [minlength] => 3 [required] => 1 ) 
) 

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

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

Любой совет / советы будут с благодарностью.

Спасибо.

Ответы [ 6 ]

9 голосов
/ 29 октября 2009

Из документов (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 () «специальными» функциями.

4 голосов
/ 23 марта 2011

Поскольку Скотт Сондерс правильно указывает документы 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
)

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

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

2 голосов
/ 19 февраля 2013

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

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

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

1 голос
/ 29 октября 2009

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

    $vars = get_object_vars($obj);

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

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

1 голос
/ 29 октября 2009

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

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;     
  }
}
0 голосов
/ 13 февраля 2010

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

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

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