我最近去了一个面试,我提供的代码有神奇的函数来获取和设置变量。我的代码如下:

public function __get($name){
    try {
        return $this->$name;
    } catch (Exception $e) {
        throw new Exception('Trying to get a variable "'.$name.'" that does not exist.');
    }
}

在采访中,他问我变量的可见性,我设置了私有变量,但是现在可以通过使用魔法函数访问它们。基本上我在这一点上没有通过面试,所以我想了解更多。我在遵循php大师的一个教程,并发现了一个不同的__get,我试图打破它,但它似乎工作,但在一个奇怪的方式。
我调用__get('test')来获取变量_test,但如果将其设置为private,它会再次调用自身并告诉我它无法访问__test。我真的不明白它为什么又叫自己。
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;

}

有谁能给我一些关于在类中使用visibility时正确使用get和set的指针,以及为什么这个函数会再次调用自己。
我已经读过这里的其他文章,但我仍然在挣扎这个概念。

最佳答案

我刚碰到这个问题,有一点可能值得澄清:
我真的不明白它为什么又叫自己。
代码不再调用自己,而是尝试执行自定义getter(如果有定义的getter)。让我分解方法执行:

public function __get($name)
{

如其他答案和here中所述,当您试图访问调用范围中未声明或不可见的属性时,将调用\uuget()magic方法。
$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));

在这里,它创建getter的名称,以便在存在时调用它。因此,如果您试图访问名为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))检查吸气剂是否can be called
如果满足这两个条件,则调用自定义getter并返回其返回值($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

高温高压

07-24 15:20