我定义当利用__get
魔术方法访问不存在的属性时会发生什么。
所以如果$property->bla
不存在,我会得到null
.
return (isset($this->$name)) ? $this->$name : null;
但是当我知道$property->bla
不存在时,我想抛出并抓住错误$property->bla->bla
。
return (isset($this->$name)) ? $this->$name : null;
我会在下面收到此错误,
<b>Notice</b>: Trying to get property of non-object in...
所以我在我的课堂上使用throw and catch
错误,
类属性{
public function __get($name)
{
//return (isset($this->$name)) ? $this->$name : null;
try {
if (!isset($this->$name)) {
throw new Exception("Property $name is not defined");
}
return $this->$name;
}
catch (Exception $e) {
return $e->getMessage();
}
}
}
但是结果不是我想要的,因为它throw
错误消息("Property $name is not defined")
而不是null
$property->bla
。
如何使其仅针对$property->bla->bla
、$property->bla->bla->bla
等抛出错误消息?
,当您调用$property->foo->bar
并且$property
类具有魔术__get方法时,您只能验证foo
属性并仅为它抛出错误。
但是,如果您的foo
也是同一类(或具有相同魔术__get
方法的类似类)的实例,则还可以验证bar
属性并引发下一个错误。
例如:
class magicLeaf {
protected $data;
public function __construct($hashTree) {
$this->data = $hashTree;
}
// Notice that we returning another instance of the same class with subtree
public function __get($k) {
if (array_key_exists($k, $this->data)) {
throw new Exception ("Property $name is not defined");
}
if (is_array($this->data[$k])) { // lazy convert arrays to magicLeaf classes
$this->data[$k] = new self($this->data[$k]);
}
return $this->data[$k];
}
}
现在只是使用它的示例:
$property = new magicLeaf(array(
'foo' => 'root property',
'bar' => array(
'yo' => 'Hi!',
'baz' => array(
// dummy
),
),
));
$property->foo; // should contain 'root property' string
$property->bar->yo; // "Hi!"
$property->bar->baz->wut; // should throw an Exception with "Property wut is not defined"
所以现在你可以看到如何让它几乎像你想要的那样。
现在只需稍微修改一下您的__construct
和魔术__get
方法,并添加新参数即可知道我们在每个级别的位置:
...
private $crumbs;
public function __construct($hashTree, $crumbs = array()) {
$this->data = $hashTree;
$this->crumbs = $crumbs;
}
public function __get($k) {
if (array_key_exists($k, $this->data)) {
$crumbs = join('->', $this->crumbs);
throw new Exception ("Property {$crumbs}->{$name} is not defined");
}
if (is_array($this->data[$k])) { // lazy convert arrays to magicLeaf classes
$this->data[$k] = new self($this->data[$k], $this->crumbs + array($k));
}
return $this->data[$k];
}
...
我认为它应该像你想要的那样工作。
你不能。
在__get()
函数的范围内,您只知道$property->blah
。你不知道它之后会发生什么,因为这是语言的功能。
请注意$foo = $property->blah->blah2->blah3
上的评估顺序:
-
$temp1 = $property->blah;
-
$temp1 = $temp1->blah2;
-
$foo = $temp1->blah3;
当然,$temp1
是虚构的,但这本质上是在执行该语句时发生的情况。您的__get()
呼叫仅知道该列表中的第一个呼叫,仅此而已。您可以做的是处理主叫端的错误,property_exists()
或检查null
:
$temp = $property->blah;
if( $temp === null || !property_exists( $temp, 'blah2')) {
throw new Exception("Bad things!");
}
请注意,如果 $temp
中返回的对象也依赖于 __get()
,property_exists()
将失败,但这在 OP 中并不清楚。