- PVSM.RU - https://www.pvsm.ru -
Как правило, мнения расходятся касательно того, хорошей ли практикой является использование публичных свойств в PHP классах или всё же стоит использовать геттеры и сеттеры (и хранить свойства приватными или защищёнными). Ещё одно, компромиссное мнение, состоит в том, чтобы использовать магические методы __get()
и__set()
.
У каждого из подходов существуют свои достоинства и недостатки, давайте взглянем на них…
Пример использования публичных свойств:
class Foo
{
public $bar;
}
$foo = new Foo();
$foo->bar = 1;
$foo->bar++;
В данном примере bar является публичным свойством класса Foo. При таком подходе мы можем манипулировать данным свойством как угодно и хранить в нём любые данные.
Достоинства публичных свойств
set
или get
) работает быстрее и использует меньше памяти чем вызов метода, но выгода от этого будет почти незаметной до тех пор, пока вы не будете вызывать метод множество раз в длинном цикле.http_build_query
).Недостатки публичных свойств
Пример использования геттеров и сеттеров:
class Foo
{
private $bar;
public function getBar()
{
return $this->bar;
}
public function setBar($bar)
{
$this->bar = $bar;
}
}
$foo = new Foo();
$foo->setBar(1);
$foo->setBar($foo->getBar() + 1);
Свойство bar
тут является приватным, в связи с этим, доступ к нему не может быть получен напрямую. Для того, чтобы получить значение свойства, вам придётся использовать метод getBar
, или setBar
для присвоения свойству значения. Чтобы вы могли быть уверенны в том, что входные данные полностью корректны, данные методы могут включать в себя соответствующий функционал для их валидации.
Достоинства геттеров и сеттеров
public function setBar(Bar $bar)
). К большому сожалению, PHP не позволяет проделывать тоже самое с типами int
и string
!Недостатки геттеров и сеттеров
$foo->bar++;
вместо $foo->setBar($foo->getBar() + 1);
(хотя, конечно, можно добавить ещё один метод $foo->incrementBar();
)get
и set
, но данные глаголы так же могут использоваться и в других методах, которые ни коим образом не относятся к свойствам класса.Пример использования магических геттеров и сеттеров:
class Foo
{
protected $bar;
public function __get($property)
{
switch ($property)
{
case 'bar':
return $this->bar;
//etc.
}
}
public function __set($property, $value)
{
switch ($property)
{
case 'bar':
$this->bar = $value;
break;
//etc.
}
}
}
$foo = new Foo();
$foo->bar = 1;
$foo->bar++;
В данном случае свойство bar
не является публичным, однако в коде оно используется так, как если бы было публичным. Когда PHP не может найти соответствующего публичного свойства он вызывает соответствующий магический метод (__get()
для получения значения, __set()
для установки значения). Данный подход может показаться золотой серединой, но у него есть существенный недостаток (см. недостатки ниже!). Следует также отметить, что __get()
и __set()
методы НЕ вызываются для публичных свойств, и вызываются в случае, если свойство помечено как protected
или private
и находится за пределами области видимости, или если свойство не определено.
Достоинства магических геттеров и сеттеров
Недостатки магических геттеров и сеттеров
@property
, @property-read
, и @property-write
. Круто.
Какой подход использовать
Очевидно, что у геттеров и сеттеров есть ряд существенных преимуществ, и некоторые люди считают, что их стоит использовать всё время (особенно те, у кого прошлое связано с Java
!). Но на мой взгляд, этим они нарушают естественное развитие языка, и их излишняя сложность и детализация принуждают меня работать с этим, даже если в этом нет надобности (меня раздражает, когда обычные геттеры и сеттеры НЕ делают ничего, кроме получения и установки свойства). В таких случаях я стараюсь использовать публичные свойства, а геттеры и сеттеры я использую для критических свойств, которые необходимо более строго контролировать, или если в них необходимо использовать отложенную загрузку данных.
Другие альтернативы?
До изучения PHP я использовал C#. В C# все свойства имеют методы доступа, но вам не нужно вызывать их как методы, вы можете манипулировать свойсвами напрямую и соответствующие методы будут вызываться магически. Это в некотором роде это похоже на магические методы __get()
и __set()
в PHP, однако свойства остаются определены и доступны. Это золотая середина и было бы очень хорошо увидеть аналогичную возможность в PHP.
Печально, но, RFC необходимый для реализации C# подобного синтаксиса определения методов доступа к свойствам не набрал необходимых две трети голосов: wiki.php.net/rfc/propertygetsetsyntax-v1.2 [1] Вот так!
Автор: Yekver
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/46144
Ссылки в тексте:
[1] wiki.php.net/rfc/propertygetsetsyntax-v1.2: https://wiki.php.net/rfc/propertygetsetsyntax-v1.2
[2] Источник: http://habrahabr.ru/post/197332/
Нажмите здесь для печати.