Я только что натолкнулся на этот вопрос, и есть кое-что, что, возможно, стоит уточнить:
Я не очень понимаю, почему он снова вызывает себя.Код не вызывает себя снова, но пытается выполнить пользовательский метод получения, если он определен.Позвольте мне разбить выполнение метода:
public function __get($name)
{
Как уже объяснялось в других ответах и здесь , магический метод __get () вызывается, когда вы пытаетесь получить доступ к свойству, котороене объявляется или не отображается в вызывающей области.
$field = '_' . strtolower($name);
if (!property_exists($this, $field)){
throw new \InvalidArgumentException(
"Getting the field '$field' is not valid for this entity"
);
}
Здесь он просто проверяет, существует ли свойство с предварительно добавленным подчеркиванием в определении класса.Если это не так, генерируется исключение.
$accessor = 'get' . ucfirst(strtolower($name));
Здесь он создает имя получателя для вызова, если он существует.Таким образом, если вы попытаетесь получить доступ к свойству с именем email
и существует закрытый член с именем _email
, переменная $accessor
теперь будет содержать строку 'getEmail'
.
return (method_exists($this, $accessor) && is_callable(array($this, $accessor))) ?
$this->$accessor() : $this->$field;
Последняя частьнемного загадочно, так как в одной строке происходит много вещей:
method_exists($this, $accessor)
.Проверяет, есть ли у получателя ($this
) метод с именем $accessor
(в нашем примере getEmail
). is_callable(array($this, $accessor))
.Проверяет, что получатель может быть вызван . - Если выполняются оба условия, вызывается пользовательский получатель и возвращается его возвращаемое значение (
$this->$accessor()
).Если нет, возвращается содержимое свойства ($this->$field
).
В качестве примера рассмотрим определение этого класса:
class AccessorsExample
{
private $_test1 = "One";
private $_test2 = "Two";
public function getTest2()
{
echo "Calling the getter\n";
return $this->_test2;
}
public function __get($name)
{
$field = '_' . strtolower($name);
if (!property_exists($this, $field)){
throw new \InvalidArgumentException(
"Getting the field '$field' is not valid for this entity"
);
}
$accessor = 'get' . ucfirst(strtolower($name));
return (method_exists($this, $accessor) && is_callable(array($this, $accessor))) ?
$this->$accessor() : $this->$field;
}
}
и затем запустите:
$example = new AccessorsExample();
echo $example->test1 . "\n";
echo $example->test2 . "\n";
Вы должны увидеть:
One
Calling the getter
Two
HTH