我最近与其他开发人员就PHP的__isset()
和__get()
魔术方法之间的关系进行了简短的讨论。它是由我们通过__get()
方法延迟加载其他对象的类引起的(延迟加载意味着该属性在首次访问之前不存在,此时对象被实例化并返回) 。不过,我们对于__isset()
应该为尚未加载的属性返回的内容有不同的看法。从技术上讲,该属性不存在(它不是 set ,或者至少,它已设置但当前为NULL
),但是对它的调用在技术上也会成功(除非例外)并返回非NULL
值。
所以,我的问题是,在这种情况下,__isset()
应该只是__get()
是否会成功获得相同参数的指标(如果TRUE
则返回__get()
将成功并返回非NULL
值。或者,它应该在技术上表现得更好,并返回FALSE
,因为数据尚不存在(即使首次访问时 )?
一个简单的例子:
class Foo {
protected $data;
public function __get($prop) {
if ($prop == 'bar') {
$this->data['bar'] = new Bar;
return $this->data['bar'];
}
}
public function __isset($prop) {
if ($prop == 'bar') {
// What goes here?
// return isset($this->data[$prop]) would mean
// that the first call to isset($foo->bar) below will be FALSE
// which means that using logic like this would always fail
// and __get() would never be called:
// isset($foo->bar) ? $foo->bar->baz : 'foo->bar not set'
}
}
}
class Bar {}
$foo = new Foo;
var_dump(isset($foo->bar)); // ???
$bar = $foo->bar;
var_dump(isset($foo->bar)); // bool(true)
答案 0 :(得分:4)
您必须从该类的用户的角度考虑这一点。假设$foo
属于class Foo
,您有以下代码:
if(isset($foo->bar)) {
var_dump($foo->bar); // #1
}
else {
// $foo->bar is "not set", right?
$x = $foo->bar;
var_dump($x); // #2
}
修辞问题:你会期望#1打印null
吗?您是否希望#2打印 null
以外的任何?
当然不是。如果它像那样工作,那么class Foo
的用户将花费大部分工作时间来诅咒作者。
假设我已经说服了你,从所期望的行为开始并回到应该如何实现它是很简单的,即像这样实现__isset
:
public function __isset($prop) {
$val = $this->$prop;
return isset($val);
}
答案 1 :(得分:0)
我认为这取决于isset()
检查对您的代码的意义。使用isset()
的代码实际上关心什么?
是否只是要求财产是价值(如,可以访问)?然后检查是否可以通过__get()
访问该值并返回结果。
是否询问该属性是否有效而不是null
?然后实际加载该值并返回结果。
是否询问该值是否已加载?然后检查是否已调用__get()
,并返回结果。
但它应该反映你的课程的使用,而不是一些任意的规则。