Accessors
| From: | Philip Thompson | Date: | Thu, 19 Feb 2009 07:11:56 +0000 |
| Subject: | Accessors | ||
| Groups: | php.general | ||
| Request: | Send a blank email to php-general+get-288592@lists.php.net to get a copy of this message | ||
Hi all.
Maybe I'm wanting more Java-like functionality out of PHP, but I don't really like getting and setting members directly (even for public members) - I'd rather use accessors. This way you can control what is getting set and what is returning. However, I also don't really want to create a million get/set accessor methods - this is no fun and takes up a lot of space. After reading around a little bit, it got me thinking about overloading in PHP (which I'm sure we all know is completely different than any other language... but that's another day). I didn't want to use the standard __get and __set methods because that still leaves me with the same notation for getting/setting members. So, instead, I used a close relative of __get and __set. Meet brother __call. Could it really be this trivial to get the notation I'm wanting? Yes. Yes it is. Ok, enough talking... onto the code.
<?php
class Person
{
public $age;
private $first, $middle, $last;
// Gotta have our construct
public function __construct () {}
// Here's the fun
public function __call ($member, $args)
{
// Since I know members I want, force the user to only
// access the ones I've created
if (property_exists ('Person', $member)) {
// If args is empty, I must be returning the value
if (empty ($args)) {
list ($value) = $this->$member;
return $value;
}
// Oh, args is not empty! Set the value
$this->$member = $args;
}
else {
// Blow up!
die ("Fatal Error: Call to undefined member: $member. Exiting...");
}
}
}
$person = new Person();
// Set the (private) first and last names
$person->first('Billy');
$person->last('Bob');
// Get the (private) first and last names
echo $person->first() . " " . $person->last()."<br/>";
// Set the (public) age
$person->age(103);
// Get the (public) age
echo "Age: ".$person->age()."<br/>";
// Explosions
$person->first = 'Buford';
$person->pizza('Is yummy');
?>
Now if you're reading this and thinking "Duh!" then good for you. However, I know there's at least 1 soul on this list who may benefit from this. But don't stop at the example above. If you want to add validation to the members you're getting/setting, build that into your code. If you want each member to be a specific type, include that as well (I'll leave the implementation up to you). ;-)
So let's recap.
• This functionality allows me to not have to write 2 accessors for every member
• This allows me to use methods instead of directly getting/setting members (even though I can still access public members directly... if I want)
• Keeps code consistent and less confusing - I know how to get and set every member
What are your thoughts? Does this seem like a reasonable implementation? Useful? Pointless? Hit me up - I can handle *constructive* criticism. But for now, it's late and past my bedtime.
Cheers,
~Philip
"innerHTML is a string. The DOM is not a string, it's a hierarchal object structure. Shoving a string into an object is impure and similar to wrapping a spaghetti noodle around an orange and calling it lunch."