PHP supports dynamic properties. Generally, I don’t find this feature to be very helpful at all, as it makes your code prone to bugs caused by property misspellings (yet another reason I’m not a huge fan of PHP at all). Take this snippet:
1 2 3 4 5 6 7 8 9 10 | class foo { public $thing = "hi\n"; } $bar = new foo; echo $bar->thing; echo $bar->thing2; $bar->ThisPropertyDoesNotExist = "Wow\n"; echo $bar->ThisPropertyDoesNotExist; |
the output will look like this:
hi Wow
Line 6 works as expected — it accesses a property defined on the object. However, let’s say line 7 was just a misspelling — you actually intended to get the value of $thing, not $thing2. There’s no error, and you just get ‘null’. What happens when you need to check $thing for null in your code and you mistyped? Bugs. Bugs are what happen. Lines 9-10 illustrate the inverse of this problem — you can just set a random, non-existant property, then later retrieve it.
I like it when code is a little tighter, so I whipped together a quick (albeit very simple) base class that will constrain properties on a PHP object. You inherit from it, and in the constructor define the allowable properties, and can even set an initial value:
class ConstrainProperties { private $data = array(); protected function __construct($props) { $this->data = $props; } protected function check_prop($name) { if (!array_key_exists($name, $this->data)) { $message = "Property does not exist: [" . $name . "]\n"; $message .= "Existing Properties:"; foreach($this->data as $k => $v) { $message .= "\n" . $k; } throw new Exception($message); } return true; } public function __set($name, $value) { if ($this->check_prop($name)) { $this->data[$name] = $value; } } public function __get($name) { if ($this->check_prop($name)) { return $this->data[$name]; } } public function __isset($name) { return isset($this->data[$name]); } public function __unset($name) { unset($this->data[$name]); } }
So, as an example, I rewrite our original “foo” class as this:
class foo extends ConstrainProperties { function __construct() { parent::__construct(array("thing" => "hi\n")); } }
Now attempting to access the “thing2″ property gets you an error:
PHP Fatal error: Uncaught exception 'Exception' with message 'Property does not exist: [thing2] Existing Properties: thing'
… and that should keep you from making spelling mistakes.
cheers