__get() 示例来自 Zandstra
Matt Zandstra 在他的文章“PHP 对象模式与实践”中给出了以下示例来说明 __get() 方法:
class Person {
function __get( $property ) {
$method = "get{$property}";
if ( method_exists( $this, $method ) ) {
return $this->$method();
}
}
function getName() {
return "Bob";
}
function getAge() {
return 44;
}
}
实际上,我们知道我们永远不会真正创建此类方法(getName 和 getAge)来返回此类静态值,而是 -我们将在对象中创建名称和年龄属性,并使用 $this 运算符返回这些属性。
我的问题是这个例子是否真的显示出实用性。如果没有,有人可以提供一个更好的例子来说明为什么人们会使用 __get() 来达到同样的目的吗?
询问的理由
如果我们要在对象中使用 name 和age 属性,那么 __get() 函数无论如何都不会被触发,因为尝试使用以下方法获取这些属性
$person = new Person();
$name = $person->name;
会导致 name 属性如果它是公共的,实际上会被返回,或者如果它是私有的或受保护的,则会导致可见性错误。在这些“真实”情况下, __get() 函数都不会被执行......我错过了什么吗?
我完全知道上面的代码是有效的。 我不相信这是一个实际的例子。
Matt Zandstra gives the following example in his text "PHP Objects Patterns and Practice" to illustrate the __get() method:
class Person {
function __get( $property ) {
$method = "get{$property}";
if ( method_exists( $this, $method ) ) {
return $this->$method();
}
}
function getName() {
return "Bob";
}
function getAge() {
return 44;
}
}
In reality, we know we would never actually create such methods (getName and getAge) to return such static values, but instead - we would create name and age properties in the object and return those using the $this operator.
My question is whether this example actually shows utility. And if it does not, could somebody provide a better example of why one would use __get() for the same sort of purpose?
Justification for asking
If we were to use name and age properties in the object, then the __get() function would not be fired anyway, because attempting to get these properties with:
$person = new Person();
$name = $person->name;
would cause either the name property to actually be returned if it were public, or cause a visibility error if it were private or protected. The __get() function would not be executed in either of these 'real' cases... am i missing something?
I'm fully aware that the above code works.
I am not convinced that it is a practical example.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你是绝对正确的——你引用一本书给我留下了深刻的印象,那个例子简直太糟糕了。
使用魔术
__get
方法来调用方法是错误的,还有其他魔术方法专门用于这种用法:__call()
__callStatic()
__invoke()
__get()
和__set()
应用于读取和写入未声明的对象属性< /em>。You are absolutely right - I am impressed that you are quoting from a book, that example just plain sucks.
Using the magic
__get
method to call methods is just wrong, there are other magic methods just for that kind of usage:__call()
__callStatic()
__invoke()
__get()
and__set()
should be used to read and write non declared object properties.神奇方法的实际功能完全取决于开发人员以他们认为合适的任何方式处理。区别在于它们的调用方式。
等等。所以如果你想让
__get()
在内部调用一个方法,你可以。您想要如何处理它完全取决于您想要如何设计应用程序。关于
__get()
,如果您有一个公共成员并尝试使用->
调用它,__get()
将不会触发。但是,如果您尝试访问不可访问的成员(受保护的、私有的或不存在的),__get()
将触发,您可以按照自己的方式处理它。据我了解,至少根据 php,
__get()
的主要目的是消除为每个成员编写 getter 的需要。与 setter 的__set()
进行比较。我不想在这里讨论这个问题,但我认为 getter/setter 的使用应该引起一些关于设计的危险信号。但是,除了应用程序开发人员的标准之外,不必遵守__get()
的预期目的。如何使用
__get()
的两个示例是初始化实例化时可能不需要的属性(例如,通过数据库查询),从而减少开销。另一种可能是,如果您将属性存储在数组中,神奇的 get 可能会返回映射到所请求属性的键的值。使用 php 魔法函数,您可以做一些非常酷的事情,并且可以通过使用这些特殊调用来编写更具可扩展性的代码。我喜欢做的事情:
当然,这是使用
__call()
而不是__get()
,但原理是一样的。在这种情况下,这只是一个健全性检查。The actual functionality of magical methods is totally up to the developer to handle in any way they see fit. The difference is in how they are invoked.
etc. So if you want to have
__get()
call a method internally, you can. How you want to handle it depends entirely on how you want to design your application.About
__get()
, if you have a public member and try to call it with->
, the__get()
will not fire. However, if you try to access a non-accessible member (either protected, private, or nonexistent)__get()
will fire and you can handle it how you like.It is my understanding that the main purpose of
__get()
at least according to php is to eliminate the need to write getters for every member. Compare with__set()
for setters. I don't want to get into this here, but I think the use of getters/setters should raise some red flags about design. However,__get()
's intended purpose does not have to be adhered to except for the standards of those developing the application.Two examples of how
__get()
might be used are to initialize a property that may not be needed upon instantiation (e.g. by a DB query) thus reducing overhead. Another may be if you have properties stored in an array, magical get may return the value mapped to the key of the requested property.With the php magic functions, you can do some very cool things and you can write code that is more extensible by using these special invocations. Something I like to do:
Of course, this is using
__call()
rather than__get()
, but the principle's the same. In this case it's just a sanity check.正如 php.net 所说
这意味着每当您尝试访问不存在或私有/受保护的属性时,都会调用
__get()
(如果已定义)。上面的示例显示了一种获取 的方法每当有人尝试获取这些私有属性的值时,调用
echo $a -> publicPropery 或 echo $a -> getPublicProperty()
即可 。但是,如果你调用 $a -> privateProperty ,你会得到一个错误,
可以了
但是只要你定义了
__get()
就 。您调用$a -> privateProperty
,执行__get()
并重定向到$a -> getPrivateProperty()
。你总会成功的获取值并仍然牢记安全性,因为您在 __get() 中检查属性 getter 是否存在,所以如果有人尝试访问不存在的属性,您可能会显示适当的错误或引发异常。属性,这将覆盖 php 的可见性错误。As php.net states
This means that
__get()
(if it's defined) is called whenever you try to access a property that does not exist or is private / protected. The above example shows a way for getting the values of those private properties by calling their accessors (getters) whenever someone tries to get the values.For example, calling
echo $a -> publicPropery or echo $a -> getPublicProperty()
would result in the same thing. However if you call $a -> privateProperty you would get an error, and
would be OK.
But, if you defined
__get()
whenever you call$a -> privateProperty
,__get()
is executed and redirected to$a -> getPrivateProperty()
. In this case you would always succeed in getting the value and still keeping security in mind. Even more, since you check for the existance of the property getter in__get()
you could show an appropriate error or throw an exception if someone tries to access unexisting properties, which will override php's visibility errors.