Объявление полей классов в PHP
Давно хотел разобраться, что будет если поле не объявлено явно в классе, но используется для чтения/записи. Периодически натыкался на такие конструкции в чужом коде, считал неверным, а потому сам никогда не использовал и ответа на вопрос «Что же все-таки будет?» не знал. Кстати, в официальном мануале ничего об этом не нашел. Буду рад, если подскажете, где просмотрел.
Итак. Поля классов могут задаваться явно с помощью ключевых слов private, protected и public, определяющих видимость поля:
class A {
private $foo;
protected $bar;
public $baz;
}
Есть еще конструкция var, но это просто устаревший аналог public.
А могут задаваться неявно, просто обращением к этому полю:
class A {
public function getFoo() {
return $this->foo;
}
public function setFoo($value) {
$this->foo = $value;
}
}
Второй способ никуда не годится:
- Неявно определенное поле получает уровень доступ
public. При явном определении — мы сразу указываем уровень доступа. - Если вызвать метод, читающий значение поля до его инициализации, то PHP сгенерирует
Notice(при первом способе его нет). А поле будет инициализировано значениемnull. - То, что это поле есть в объекте, не получится узнать через
Reflection,property_existsиget_class_vars. Только черезissetиget_object_vars, и то только, если полю было присвоено значение. - С такими полями неудобно работать в редакторе — IDE их не подсказывает и вообще подсвечивает, как ошибочные. Можно описать эти поля с помощью PHPDoc тегами
property, но непонятно, почему бы тогда не описать их явно как поля класса :).
В общем, не пользуйтесь никогда вторым способом. Он усложняет и запутывает код и является источником ошибок. Единственно, когда он имеет право на существование — это динамическое создание полей объекта. И даже тогда можно справиться геттерами и сеттерами (правда с потерями в производительности, при малом количестве вызовов потери незначительны).