3

I've had a good read of the PHP specs on overloading, and most of the examples appear to be intended to simply allow defining of custom fields (similar to stdClass).

But what about the private fields defined in my class? How should these be retrieved/assigned? I could do a switch on possible values and act on certain values:

class A
{
    private $name;
    private $age;

    public function __get( $var )
    {
        switch ( $var )
        {
            case 'name':
                return $this->name;
                break;
            case 'age':
                return $this->age+10; // just to do something different ;)
                break;
            default:
                break;
        }
    }
}

Is this the best method, or is there another generally accepted best practice? (I don't know if it's possible to loop class variables inside a class, but regardless that's not appropriate in most situations since you don't want to return everything.)

DisgruntledGoat
  • 70,219
  • 68
  • 205
  • 290
  • Are you trying to make just read-only properties? Or are you trying to implement property specific getter/setter logic within the `__get` and `__set` methods? If the latter is true, you really should just be writing getter and setter methods... ie, `getAge` and `setAge` as the API and logic encapsulation is much clearer. – jason Jul 25 '09 at 04:05

3 Answers3

11

I make extensive use of __get() and __set() AND I have my properties declared public. I wanted the best of both worlds, so my IDE could list public properties for me when I type the name of a class instance. How did I get the PHP interceptor methods to work, even though the properties are public and visible outside the class?

unset() the properties I want __get() and __set() to be used for in the class __construct().

Figuring this method out took a couple evenings of frustration :-)

grantwparks
  • 1,124
  • 9
  • 13
  • for the sake of IDE completion you can just list @property 'ies in the docBloc of the class. – raveren May 04 '12 at 09:51
  • @Raven - so I'm guessing then that would make private properties satisfy the autocomplete. But I designed things to rely on __get and __set for lazy loading, etc, which wouldn't have happened during class access of its own privates. There were multiple design goals to be solved. – grantwparks May 05 '12 at 23:25
  • 1
    yeah I got all that, it's just an additional FYI – raveren May 09 '12 at 13:13
2

This would effectively make them public, and usually this gains you nothing over simply using public properties (but you pay performance penalty and have to write more code, risk bugs).

Use that only if you have existing code that uses public property and you suddenly need getter/setter for it (like your example with age).

If you need to execute some code when property is read/written (e.g. make it read-only or lazily fetch from the database), then you should use normal getters/setters (getAge()/setAge()).

Kornel
  • 97,764
  • 37
  • 219
  • 309
  • 1
    It gains me a lot. My classes have a lot of properties which come from different tables, and an individual script execution (read: trip to the server) is only going to be interested in a very small subset of them. I use __get() to only fetch them once, when they are referenced (I also at the same time fetch any other properties that available from the same query). On a high volume site, this method has drastically reduced database access. I can also impose security on each property, based on the session's role. – grantwparks Jul 27 '09 at 15:13
  • @grantwparks: I think that falls under "unless you need getter/setter" exception. – Kornel Jul 27 '09 at 15:41
1

I don't see many people using them, but here is what I think.

For retrieving private variables, you probably want to give a list of defined variables that are able to be accessed by the outside. Then, check to see if the requested variable is in that array. If it is, allow it to be changed/gotten. If not, either error or return null.

Honestly, the implementations for this are really case-by-case. If you had a user class that you stored all the info in a single array, you could have $user->name be pulled from $user->account['name'], or something like that.

Also, in a more case-by-case, you could do some modification before giving them values, like hashing a password.

Tyler Carter
  • 60,743
  • 20
  • 130
  • 150