[英]__get magic method - how to throw and catch error for property overloading?
I define what happens when a non-existent property is being accessed by taking advantage of the __get
magic method.我定义了利用
__get
魔术方法访问不存在的属性时会发生什么。
So if $property->bla
does not exist I will get null
.因此,如果
$property->bla
不存在,我将得到null
。
return (isset($this->$name)) ? $this->$name : null;
But I want to throw and catch the error for $property->bla->bla
when I know that $property->bla
does not exist.但是当我知道
$property->bla
不存在时,我想抛出并捕获$property->bla->bla
的错误。
with return (isset($this->$name)) ? $this->$name : null;
return (isset($this->$name)) ? $this->$name : null;
return (isset($this->$name)) ? $this->$name : null;
I will get this error below,我将在下面收到此错误,
<b>Notice</b>: Trying to get property of non-object in...
So I use throw and catch
error in my class,所以我在课堂上使用
throw and catch
错误,
class property {类属性{
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();
}
}
} }
But the result is not what I want because it throw
the error message ("Property $name is not defined")
instead of null
for $property->bla
.但结果不是我想要的,因为它
throw
错误消息("Property $name is not defined")
而不是$property->bla
的null
。
How can I make it to throw error message only for $property->bla->bla
, $property->bla->bla->bla
, and so on?我怎样才能让它只为
$property->bla->bla
、 $property->bla->bla->bla
抛出错误消息?
You can't.你不能。
Within the scope of the __get()
function, you only know about $property->blah
.在
__get()
函数的范围内,您只知道$property->blah
。 You have no clue what comes after it, because that's the functionality of the language.你不知道它后面是什么,因为那是语言的功能。
Note the order of evaluations on $foo = $property->blah->blah2->blah3
:请注意
$foo = $property->blah->blah2->blah3
上的评估顺序:
$temp1 = $property->blah;
$temp1 = $temp1->blah2;
$foo = $temp1->blah3;
Of course, $temp1
is fictitious, but this is essentially what happens in the execution of that statement.当然,
$temp1
是虚构的,但这本质上是在执行该语句时发生的情况。 Your __get()
call is only aware of the first call in that list, and nothing more.您的
__get()
调用只知道该列表中的第一个调用,仅此而已。 What you can do is handle the error on the calling side, with property_exists()
or check for null
:您可以做的是在调用端处理错误,使用
property_exists()
或检查null
:
$temp = $property->blah;
if( $temp === null || !property_exists( $temp, 'blah2')) {
throw new Exception("Bad things!");
}
Note that property_exists()
will fail if the object returned in $temp
also relies on __get()
, but that was not clear in the OP.请注意,如果
$temp
返回的对象也依赖于__get()
,则property_exists()
将失败,但这在 OP 中并不清楚。
Actually, when you calling $property->foo->bar
and $property
class have magic __get method, you can verify only foo
property and throw error only for it.实际上,当您调用
$property->foo->bar
和$property
类具有魔术 __get 方法时,您只能验证foo
属性并仅为它抛出错误。
But if your foo
is also an instance of the same class (or similar class with the same magic __get
method) you can also verify bar
property and throw the next error.但是,如果您的
foo
也是同一类(或具有相同魔术__get
方法的类似类)的实例,您还可以验证bar
属性并抛出下一个错误。
For example:例如:
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];
}
}
And now just example of using it:现在只是使用它的例子:
$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"
So now you can see how to made it almost like you want.所以现在你可以看到如何让它几乎像你想要的那样。
Now just modify a little your __construct
and magic __get
methods and add new param to know where we are at each level:现在只需稍微修改您的
__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];
}
...
I think it should works like you want.我认为它应该像你想要的那样工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.