我定义了利用__get
魔术方法访问不存在的属性时会发生什么。
因此如果$property->bla
不存在,我会得到null
。
return (isset($this->$name)) ? $this->$name : null;
但是当我知道$property->bla->bla
不存在时,我想抛出并抓住$property->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
的{{1}}。
如何让它为$property->bla
,$property->bla->bla
抛出错误消息 ,等等?
答案 0 :(得分:2)
你不能。
在__get()
函数的范围内,您只知道$property->blah
。你不知道它后面会发生什么,因为这是该语言的功能。
请注意$foo = $property->blah->blah2->blah3
上的评估顺序:
$temp1 = $property->blah;
$temp1 = $temp1->blah2;
$foo = $temp1->blah3;
当然,$temp1
是虚构的,但这基本上就是在执行该语句时发生的事情。您的__get()
电话只知道该列表中的第一个电话,仅此而已。您可以做的是使用property_exists()
或{0}}检查主叫方面的错误:
null
请注意,如果$temp = $property->blah;
if( $temp === null || !property_exists( $temp, 'blah2')) {
throw new Exception("Bad things!");
}
中返回的对象也依赖property_exists()
,$temp
将失败,但OP中并不清楚。
答案 1 :(得分:1)
实际上,当您调用$property->foo->bar
和$property
类具有magic __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];
}
...
我认为它应该像您想要的那样。