PHP class def: Individual accessors/mutators or __set() with switch()?
coding-style, oop, php
Solution
Go with the individual accessors for each and every member you want to be accessible from outside. I have tried both and found these reasons to use the accessors:
- Whatever you use to document your API (doxygen/PHPdoc/Zend), the generated docs won't show the members that are accessible through magic functions.
- You can document the accessors. You really ought to be able to put a line like this in the documentation: "IMPORTANT! This function connects to the database, it will be really slow, use otherFunction() if you can."
- The implementation of the accessor is easily visible for anyone. I wouldn't want to dig into the details of a 200-line magic function to check if the accessor does anything besides setting/getting the value (that's why we're writing accessors after all.)
- You already mentioned the autocompletion of IDEs.
- The __get() function has a well-defined function header, so you won't be able to create getters that return a reference, for example (which is really great when working with arrays, i.e. `$numbers = &$object->getNumbers(); $numbers[] = 4;` - without the reference, you would need to call the setter again.)
Problem
When defining a PHP class, which is preferred/best practice? Are there any key differences I'm overlooking? It seems like it could be more clean, concise, and convenient to write a `__set()` magic method and put a `switch()` construct in it with cases for all the private members to which I want to allow access. It wouldn't be called automagically from inside the class, but then again neither would `setFoo()`, so if I want to use the accessor/mutator internally, I'd have to explicitly call a method either way. The other difference is that in the code outside the class, I could always access member vars in the same fashion as `$obj->foo`, whether public (directly) or private (using `__set()`), versus using many separate methods. I guess this comes down mostly to an aesthetic choice. For example, if I have address data on a purchase, I don't want to have 16 or more separate accessor methods just for first name, last name, address1, address2, city, state, etc. each for shipping and billing data. Are there any key differences I've overlooked? (Might a sophisticated IDE refuse to auto-complete a member name outside the class because it's marked as private?) Have I pretty much answered my own original question? Thanks in advance for your input.