tags:

views:

263

answers:

7

I always thought you should never set/get a member variable directly. E.g.

$x = new TestClass();
$x->varA = "test":
echo $->varB;

I thought you should always use object methods to access member variables.

But I've just been looking at __set and __get, which imply it's ok to access members directly.

Any thoughts?

A: 

Prior to PHP 5, you could do that. With the introduction of PHP 5, you can declare private variables. So it's not unusual to see PHP 4 codes which access variables directly because there is no rules for private variables.

Extrakun
Java/C# and other "classical" OOP languages have/had their own reasons for not directly accessing member variables, it wasn't/isn't just a PHP4 thing.
Alan Storm
A: 

I think it's ok to access class variables directly. If you want to keep other classes from modifying those variables you can make them private. If you have a public getter and setter that strictly copies the value passed to class field I think that's just overcomplicated approach.

The only situation I can think of where you would want to use getter or setter is when you have to process the value somehow.

RaYell
A: 

The right thing to do from a purist OO perspective is create your own setter/getter method (ideally by overloading PHP's) that makes the relevant data available. (PHP is effectively providing you with generic versions of this with __get and __set, but these will let you get/set anything, which most likely isn't ideal.)

You should also set all of the variables (and indeed methods) within a class to have the correct visibility (private, protected, etc.) hence forcing you to use the set/get methods.

middaparka
A: 

Look at the manual:
http://us2.php.net/manual/en/language.oop5.magic.php

Magic Methods
The function names __construct, __destruct, __call, __callStatic, __get, __set, __isset, __unset, __sleep, __wakeup, __toString, __invoke, __set_state and __clone are magical in PHP classes. You cannot have functions with these names in any of your classes unless you want the magic functionality associated with them. 

Caution
PHP reserves all function names starting with __ as magical. It is recommended that you do not use function names with __ in PHP unless you want some documented magic functionality. 

Just do good OOP ( I suggest you to declare getters and setters against accessing variables directly..) and forget about __get and __set.. If I'm not wrong there is also a __call for calling arbitrary methods.They are MAGIC methods they aren't meant for ordinary operations.

You shouldn't be using __get and __set or __call unless you are writing very particular code (es some framework, or something for proxying calls to other objects like in the php library Javabridge http://php-java-bridge.sourceforge.net/ ).

mic.sca
+3  A: 

There's no right answer here.

In the beginning, direct access to member variables was considered a bad idea because you lose the ability to make that access conditional upon some set of arbitrary programming logic. That's why we have the terror of getter and setter methods.

Having magic methods like __set and __get removes this concern. You can have users of your object access member variables all you want and then if you discover you need some programatic logic around that access, you can use the magic methods.

However, particularly in PHP, __set and __get aren't free from a performance perspective. Also, remember that __set and __get are only invoked when an inaccessible (private, protected, etc.) member variable is accessed. This means there's no way to invoke __set and __get from within a class, outside of removing the member variable from the class definition, which makes your class less clear.

Like most things PHP, there's no clear "best" way to handle this.

Alan Storm
Thanks Alan. That makes sense. What are your thoughts on having a single function to set/get a variable instead of two? e.g. public function name ( $_name = NULL ) { if ( is_null( $_name ) ) { return $this->name } else { return $this->name = $_name } }
aidan
I personally wouldn't like that. You make code less clear in that, when you see a call to the "name" method it's not clear if the user wanted to get or est a variable, which can make bugs trickier to track down.
Alan Storm
+2  A: 

Not only in PHP but in object oriented programming in general, if a class has member variables for which it's not necessary to execute code when they are accessed, there's no need to make setters and getters, and the variables can be accessed directly.

Petruza
How do you know what member variables are going to need to have code executed when they're accessed?
Alan Storm
When you design. Anyway, you can always change the source code.
Petruza
+1  A: 

Accessing properties (variables) of an object is OK if those are public.

If they are protected/private (which is something new in PHP 5, that didn't exist in PHP 4), you can't access them directly.

Doing this or going through accessors depends on what you need / want to do :

  • if you only want to access data, you do not need accessors
  • if you want to perform some actions when data is accessed (check for the correctness of a value, for instance), you should use accessors -- bet it maginc method __get/__set or not.
  • Using those two magic methods has the advantage that it is transparent for the user ; and you can add them whenever you want, without forcing your users to rewrite their code.
  • But note that using getters/setters is said to have a cost (it costs some CPU, when you speak about performance, as you have to call a method)

In the end, there is no "right way", not "best way" : there are two ways, and it's up to you to choose which one fits the best for your needs.

For my own projects, here's what I generally do :

  • when I don't need to check anything, I don't use getters/setters
  • when I need some special behaviour, I declare my variables as protected/private, and create a special getter/setter (like getName/setName)
    • this has the advantage of having a phpdoc for each method, and hinting in the IDE I use, btw
Pascal MARTIN