Я новичок в php. Я знаю, что __set () и __get () создают защищенное свойство, но оно ведет себя как открытое свойство. И свойства, созданные этим методом, имеют значение PROTECTED. Но единственное отличие состоит в том, что к ним можно получить доступ в любое время из любого места так же, как публичные свойства. Поскольку у меня нет практического опыта работы на PHP, я хотел бы знать, почему бы не создать открытое свойство вместо того, чтобы использовать __get () и __set ()??Также свойство __set () создает свойство во время выполнения.Создает ли это проблему при отслеживании всех свойств объекта???
class foo {
protected $another='lol'; //protected propertypublic function __get($name) {return $this->$name;
}
public function __set($name, $value) {$this->$name = $value;
}
}
class bar extends foo{ // inherits from foo
public function __get($name){ //__get() method for bar class
return $this->$name; //
}
}
$foo = new foo();
$foo->bar = 'test';
echo $foo->another; //echos protected property from parent class
echo '</br>';
$bar=new bar();
echo $bar->another; // echos inherited private property from parent class
var_dump($foo);
Это все связано с инкапсуляцией данных в классе, так что внешний мир не может напрямую изменять значения этих данных. Если вы неоднократно устанавливаете значения переменной из внешнего класса, вы можете подумать о том, должна ли изменяемая переменная находиться в ее текущем классе. Вы также можете лучше контролировать доступность переменной. Например, просто предоставив метод get () и не позволяя себе устанавливать значение, когда вы не должны этого делать. Наличие метода для установки значения чего-либо также предоставляет очень удобное место для проверки, вместо проверки значений вне класса, где вы можете время от времени забывать. Кроме того, защищенные свойства отличаются от общедоступных свойств, поскольку к ним нельзя получить доступ где угодно, только в собственном классе переменной или в классах, унаследованных от класса, в котором находится переменная.
Существует очень мало причин использовать __get, __set (или __call в этом отношении) таким образом, чтобы фактическая структура данных была фиксированной (например, у вас есть фиксированный набор членов и доступ к ним только через эти методы.
Преимущество этих методов заключается в ситуациях, когда у вас нет фиксированной структуры. Хотя таких ситуаций обычно следует избегать, в некоторых ситуациях это может оказаться полезным.
Например, у меня есть класс модели для очень легкого ORM, который не требует генерации кода и все еще имеет открытый интерфейс, похожий на более сложные среды стилей ActiveRecord (в этом я использую __call и извлекаю имя поля из вызываемого метода, но __get / __ set также будет работать).
class User extends AbstractModel {
protected static $FIELD_LIST = ['id', 'username', 'password'];
}
$foo = new MyModel();
$foo->setId(123);
$foo->setUsername('Foo');
$foo->setPassword('secret');
$foo->setNonExistantField('World!'); // will throw an exception
Это позволяет мне быстро создать класс модели, в котором в любой момент я могу написать собственный метод установки. например если бы я хотел сохранить этот пароль как соленый хеш, я мог бы сделать что-то вроде этого:
class User extends AbstractModel {
protected static $FIELD_LIST = ['id', 'username', 'password'];
public function setPassword($password) {
$salt = magic_salt_function();
$hash = crypt($password, '$2a$08$' . $salt);
$this->data['password'] = $hash;
}
}
Преимущество в том, что мне не нужно писать методы получения / установки для каждого поля, но в любой момент можно. Очень удобно в быстром прототипировании.
Подобные методы можно использовать, например, если у вас есть данные в массиве, которые вы хотите изменить с помощью синтаксиса объекта. Использование __get / __ set позволяет избежать необходимости проходить через массив всякий раз, когда вы покидаете контекст объекта обратно в контекст массива.
class Foo {
protected $data;
public function __construct(array $data) {
$this->data = $data;
}
public function __get($key) {
if(!isset($this->data[$key])) {
throw new Exception("Unknown member $key");
}
return $this->data[$key];
}
public function __set($key, $value) {
if(!isset($this->data[$key])) {
throw new Exception("Unknown member $key");
}
$this->data[$key] = $value;
}
public function getData() {
return $this->data;
}
}
$data = [
'bar' => true,
'braz' => false
];
$foo = new Foo($data);
$foo->bar = false;
$foo->braz = true;
$foo->nope = true; // will throw an exception
В конце концов, перегрузка в PHP — это инструмент для довольно специфической задачи (создание динамических интерфейсов). Если вам это не нужно, вы его не используете. И когда вы используете его, вы должны знать, что у него есть свои недостатки. В конце концов, когда вы перегружены, вы отвечаете за проверку, что обычно переводчик может сделать для вас.