Обработка свойств PHP, подобных свойствам в C# (геттер и сеттер)
Я проводил некоторое исследование в течение долгого времени и хотел знать, можно ли использовать свойства в классе PHP, как в C#, я нашел эти вопросы, которые дают несколько хороших ответов и указателей, но на самом деле не помогли мне:
- Должен ли я использовать обработку свойств, подобную C#, в PHP?
- Получить и установить (частное) свойство в PHP, как и в C#, без использования перегрузки магического метода getter setter
Хотя, как я уже сказал, они дают хорошие ответы, я все еще не могу определиться с этим, например, я хочу иметь возможность делать что-то вроде:
class Foo
{
public $bar
{
get { return $this->bar; }
set { $this->bar = value; }
}
}
Но я не могу!
Каков наилучший способ сделать это в рамках ограничений PHP?
Вот что я смог придумать:
class user
{
private static $link;
private static $init;
private function __construct ()
{
global $link;
static::$link = $link;
}
public static function __INIT__ ()
{
return static::$init = (null === static::$init ? new self() : static::$init);
}
public static $username;
public function username( $value = '' )
{
if ( $value == '' || empty ( $value ) || !$value )
return static::$username;
else
static::$username = $value;
}
}
2 answers
Для этого и существуют волшебные методы PHP. Они позволяют динамически задавать свойства с помощью метода посредника. Здесь позвольте мне показать вам пример:
abstract class GetterSetterExample
{
public function __get($name)
{
$method = sprintf('get%s', ucfirst($name));
if (!method_exists($this, $method)) {
throw new Exception();
}
return $this->$method();
}
public function __set($name, $v)
{
$method = sprintf('set%s', ucfirst($name));
if (!method_exists($this, $method)) {
throw new Exception();
}
$this->$method($v);
}
}
class Cat extends GetterSetterExample
{
protected $furColor;
protected function getFurColor()
{
return $this->furColor;
}
protected function setFurColor($v)
{
$this->furColor = $v;
}
}
$cat = new Cat();
$cat->furColor = 'black';
Да... меня это тоже пугает.
Вот почему большинство людей довольствуются использованием методов, подобных описанным в Cat
, но общедоступных. По-видимому, обсуждается вопрос о добавлении "настоящих" геттеров и сеттеров, но, похоже, существует много конфликтов между теми, кто ненавидит их из-за проблем с удобочитаемостью, семантикой и принцип...
Может быть, вам нужно подумать, действительно ли это необходимо. Это просто стенография для написания геттеров и сеттеров.
private String _name;
public String Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
Выполняет точно такую же функцию, как:
private $_name;
public function getName()
{
return $_name;
}
public function setName($name)
{
$_name = $name;
}
Есть только разница в вызове:
C# : Object.Name = "This is my Name";
PHP : Object->setName ("This is my Name");
Если вы действительно предпочитаете синтаксис C# (что, на мой взгляд, просто привычка), я думаю, что ответ Флоскулуса - единственный вариант. Это не так сложно, если вы понимаете, что делает код. Для информации:
__set() is run when writing data to inaccessible properties.
__get() is utilized for reading data from inaccessible properties.
В этом примере furColor
является недоступна, так как это защищенная переменная.
Так что же здесь происходит $cat->furColor = 'black
.
- Furcolor недоступен, поэтому вызывается магический метод __set.
- Он создает сеттер в
GetterSetterExample
с именемsetFurColor
и проверяет, существует ли он. - Да, он существует, потому что
Cat
реализовал его. -
setFurColor
вызывается и устанавливается переменная.
В финале также этот код выполняет то же самое, что и общие геттеры и сеттеры из приведенного выше примера. Это просто "обходной путь" для имитации свойств C#. Итак, возвращаясь к моему первому вопросу этого ответа, необходимо ли это? На мой взгляд, это не так. PHP не поддерживает свойства, поэтому не имеет четкого смысла, почему вы пытаетесь его имитировать. Общие геттеры и сеттеры - это правильный путь, и, как показано в моих примерах, он делает то же самое. Магические методы медленны, и удачи, если вы хотите сделать это безопасным способом. Пример кода Flosculus не является сложным, но это приложение может стать (ненужный) комплекс.