__get() example via Zandstra
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.
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.
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.
$obj->property; // invokes __get(), if defined
$obj->method(); // invokes __call(), if defined
$obj(); // invokes __invoke() if defined (php 5.3+)
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:
class application {
public function __call($_, $_) {
throw new Exception("PUT and DELETE not supported");
}
public function POST() {
//update data
header("Location: $_SERVER[PHP_SELF]", true, 303);
}
public function GET() {
//display data
}
public static function inst() {
return new self;
}
}
application::inst()->$_SERVER['REQUEST_METHOD']();
Of course, this is using __call()
rather than __get()
, but the principle's the same. In this case it's just a sanity check.
As php.net states
"__get() is utilized for reading data from inaccessible properties."
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
$a -> getPrivateProperty()
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.
<?php
class data {
public $name="Ankur DalsaniYa"; \\ I wont to change name
public function __get($var) {
print "Attempted to retrieve '<b>$var</b>' and failed...\n";
//$var is print the Unknown and Not Define but call variable print
}
}
$data = new data;
echo "<br> Not Define Variable Call : ";
print $data->title; // Not Defined variable Call then call __get function
echo "<br><br> Define Variable Call : ";
print $data->name; // Define variable Call then Not call __get function
?>
精彩评论