Hacking together PHP Properties

Some of you are probably aware that there’s an RFC for PHP to get property support. Man I want that… but I just discovered how to fake it AND keep autocomplete support in my favorite editor – Komodo Edit! This is all documented in various pieces online, but it took me awhile to pull it all together, so maybe this will save someone a little time.

First, make all your properties (yes, PHP calls them properties even though they’re just instance variables) protected[1]. Then, add the __get method:

public function __get($name) {
    if(property_exists($this, $name)) {
        return $this->$name;
    }

    $trace = debug_backtrace();
    trigger_error('Undefined property via __get(): '.$name.' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE);
    debug_print_backtrace();
    return null;
}

Great, so now you have read only properties! But… what if we want to write to them? Magic variable names to the rescue! I postfix my variables with “_” to indicate write only. And of course, if you want read/write, just make the property public in the first place. So the write only enforcing setter is;

public function __set($name, $value) {
    $name .= "_";
    if(property_exists($this, $name)) {
        $this->$name = $value;
    }

    $trace = debug_backtrace();
    trigger_error('Undefined property via __set(): '.substr($name, 0, -1).' in '.$trace[0]['file'].' on line '.$trace[0]['line'], E_USER_NOTICE);
    debug_print_backtrace();
}

Great! Uh… now code completion doesn’t work. Fortunately, the great folks at PHPDoc anticipated this, and have @property tags! Just add them to your main class comment (you are commenting your code, right?), using @property-read and @property-write for your respective visibilities.

Now I realize that this isn’t exactly the C# style properties we all know and love – for instance, while you could special case some property name to do something special on update, it involves string comparison which is cluggy and slow. Still, this at least gets me out of cluttering my classes with accessor methods while maintaining some sanity in what I expose in my classes. Hopefully PHP will get its act together and implement all these cool new features, but until then, enjoy some fake properties.[2]



[1]Private is evil, and should be banned. The problem with private is that someone (maybe even you) comes along and wants to subclass your library to do really clever thing x, which would have been SO EASY if they had access to your private property. But they don’t, because you made it private. What’s the real use case of private/protected? To keep people from interacting with your library in stupid ways – changing state when you don’t expect it. And since sublassing is extending the library, not actually using the library, protected still accomplishes this without crippling the power of extension!

[2]I’d like to take a minute to vent about this bug I filed back in December. It’s a memory issue with static methods calling type hinted constructors with bad arguments. And it’s still not fixed. There’s no sign of it being fixed. Ok, in fairness, they fixed it just enough to get the error to propagate to the apache error log, but not enough to stop the segfault. So, now I can at least distinguish it from the three other segfaults I get every day I work on this project…

About Bion

I'm a software developer at Modo Payments, a mobile payment provider. When I'm not hacking away the office, you I'm usually at home hacking on something else. Or practicing Aikido. Anyway, I just post things here that Google couldn't help me with, so maybe it'll help you in the future. Since you're reading this, I guess it worked :)
This entry was posted in Technology and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *