我一直在阅读PHP magic methods,并试图更好地理解它们。从PHP手册中可以看出:
在与尚未声明或在当前作用域中不可见的属性或方法交互时,将调用重载方法。
我已经阅读了“不visible”的含义:
可以通过在声明前加上关键字public,protected或private来定义属性,方法或(从PHP 7.1.0开始)常量的可见性。
请考虑下面的课程:
<?php
class MyClass{
private $x = 1;
protected $y = 2;
public $z = 3;
public __construct(){}
function __get($name){
switch(true){
case ($name == 'x'):
return 4;
case ($name == 'y'):
return 5;
case ($name == 'z'):
return 6;
case ($name == 'w'):
return 0;
}
}
function sum(){
return $this->x + $this->y + $this->z;
}
}
?>
因此,考虑到上面关于“可见”和“范围”的片段,在什么情况下调用__get
魔法,什么时候不调用?
如果我实例化一个新对象:$myclass = new MyClass()
,$myclass->sum()
会返回6
或15
还是别的?
如果我致电$myclass->x
,$myclass->y
,$myclass->z
,结果将是4
,5
和3
,因为{{ 1}}和x
在技术上不是“可见的”?
我假设调用y
将返回$myclass->w
而不考虑范围,因为它从未被定义为类的属性,是吗?
答案 0 :(得分:1)
因此,考虑到上面关于“可见”和“范围”的片段,在什么情况下调用
__get
魔法,什么时候不调用?
当访问对象上不存在的属性时,或者从无法访问属性的范围访问属性时,将调用__get
方法。例如,$obj->foo
将始终触发__get
,而$obj->x
会在从课堂外调用时触发__get
。
如果我实例化一个新对象:
$myclass = new MyClass()
,$myclass->sum()
会返回6或15或其他内容吗?
它将返回6(1 + 2 + 3
)。 $this->x
,->y
和->z
都可以在课程中访问,因此此处不会触发__get
方法。
如果我拨打
$myclass->x
,$myclass->y
,$myclass->z
,结果会是4,5和3,因为x和y在技术上并非“可见”,会怎样?
正确。
我假设调用
$myclass->w
将返回0而不考虑范围,因为它从未被定义为类的属性,是吗?
正确,只要您没有明确地为$myclass->w
分配值。
答案 1 :(得分:1)
class MyClass {
private $x = 1;
protected $y = 2;
public $z = 3;
// ...
}
在MyClass
类的代码中,所有实例属性($x
,$y
和$z
)都是可见的。 sum()
函数会看到它们,当它使用它们时,无需调用__get()
。
如果代码尝试访问同一类的另一个对象的protected
或private
属性,也会发生这种情况。例如:
class MyClass {
private $x = 1;
protected $y = 2;
public $z = 3;
public function copyFrom(MyClass $that) {
$this->x = $that->x;
$this->y = $that->y;
$this->z = $that->z;
}
}
$a = new MyClass();
$b = new MyClass();
$b->copyFrom($a);
copyFrom()
方法可以访问$that
对象的所有属性(因为它与$this
具有相同的类)并且不会调用__get()
。
但是对于这段代码:
$a = new MyClass();
echo($a->x + $a->y + $a->z);
魔术方法__get()
被调用两次,适用于$a->x
和$a->y
,因为这些属性在MyClass
类之外的代码中不可见。
作为一般规则,如果类没有定义__get()
方法,当访问不可见的属性进行读取时,解释器会触发致命错误:
PHP致命错误:未捕获错误:无法访问私有属性MyClass :: $ x
__get()
的存在可以抑制错误。而是调用__get()
,并使用它返回的值。如果__get()
没有返回值(无论为什么),则使用NULL
代替(这是函数的标准PHP行为)。