tags:

views:

1184

answers:

7

I'm kind of new in PHP. For some reason in other types of programming languages like JAVA I have no problem with using setters and getters for every single variable, but when I'm programming in PHP probably because it is so flexible it feels kind of like a waste of time. It feels simpler to just set the class attributes as public most of the time and manipulating them like that. The thing is that when I do it like this I feel like I'm doing something wrong and going against OO principles.

Is it really that wrong not using setters and getters? Why or why not? How do you guys do it most of the time?

+12  A: 

The point of getters or setters is that you can still add logic to your modifications of the field in one place instead of everyplace you want to modify or retrieve the field. You also gain control at class level what happens with the field.

Tomh
+3  A: 

Did you consider to use magic functions __set/__get? Using them you can easily merge all getter/setter function in only 2 functions!

Valentin Jacquemin
Sort of. Remember that __set and __get are only called if you attempt to access a property that's inaccessible. This means if you want to use __get and __set you need to completely eschew defining properties, which comes with it's own set of headaches. (of course, you don't HAVE to completely eschew defining properties, but if you have a mixed defined properties and undefined properties you end up confusion and ambiguity, and avoiding confusion and ambiguity is what we (should) mean by "best practices".
Alan Storm
@Alan, I think all you would need to do is define the properties as "protected" or "private". This makes them inaccessible. http://php.net/language.oop5.overloading
sirlancelot
@sirlancelot, You can define them as private or protected, but they're still accessed directly within *some* scope. Depending on the complexity of logic in your setter/getter, this can be a real pain.
Adam Backstrom
+8  A: 

The main problem with not using property accessors is that if you find out you ever need to change a field to a property later on - to make it a computed property in a subclass, for instance - you'll break clients of your API. For a published library, this would be unacceptable; for an internal one, just quite a lot of work fixing things.

That said, for private code / small apps, it could be feasible to just wing it. A sane editor / IDE will let you generate the clutter needed for the accessors and hide it in a folding block though, so it's arguably just easier to do this mechanically.

Note that some programming languages have features to synthetise the default field+getter+setter - Ruby does it via metaprogramming, C# has auto-implemented properties. And Python sidesteps the issue completely by letting you override attribute access, letting you encapsulate the attribute in the subclass that needs it instead of having to bother with it up front, which is my favourite approach.

Sii
+1  A: 

If you access these variable in your script lots of time and if you update yoru class often you should use setters and getter because but if you dont this , when you improve your class you have to update all files which uses this variable .

Secondly main reason why you do this is you should not access variable directly because class structure may change and this data can be providen differently.While you are getting data from class you should not care about how this data is generated .Class have to care about this data proccessing so you only should care what will you get.

Oguz
+5  A: 

I am probably not going to get many upvotes on this one, but personally getters and even more so setters feel like a code smell to me. Designs should be behavior driven, not data driven. Of course, this is just an opinion. If you have an object that depends on a particular data field of another object this is very tight coupling. Instead it should depend on the behavior of that object which is far less brittle than its data.

But yes, property like getters and setters are a step up from a dependency on a field directly for this very reason. It is less brittle and loosens up the coupling between the objects.

nightski
Belongs into http://stackoverflow.com/questions/406760/whats-your-most-controversial-programming-opinion ;)
J. Random Coder
+1  A: 

There is a way to emulate get/set without actually using get/set function class, so your code remains tidy:

$person->name = 'bob';
echo $person->name;

Take a look at this class I have coded.

Typically, when using this class, you would declare all your properties protected (or private). In the event where you'd want to add a behaviour on a property, say strtolower() + ucfirst() on the "name" property, all you'd need to do is declare a protected set_name() function in your class and the behavior should get picked up automatically. Same can be accomplished with get_name().

// Somewhere in your class (that extends my class).
protected function set_name($value) { $this->name = ucfirst(strtolower($value)); }
//

// Now it would store ucfirst(strtolower('bob')) automatically.
$person->name = 'bob';

P.S. Another cool thing is you can make up non-existing fields such as

echo $person->full_name;

without having such fields (as long as there is a get_full_name() function).

Mario
+6  A: 

If we're talking strictly about PHP here and not about C#, Java, etc (where the compiler will optimise these things), I find getters and setters to be a waste of resources where you simply need to proxy the value of a private field and do nothing else.

On my setup, I made two crappy classes, one with five private fields encapsulated by five getter/setter pairs proxying the field (which looked almost exactly like java code, funnily enough) and another with five public fields, and called memory_get_usage() at the end after creating an instance. The script with the getter/setters used 59708 bytes of memory and the script with the public fields used 49244 bytes.

In the context of a class library of any significant size, such as a web site framework, these useless getters and setters can add up to a HUGE black hole for memory. I have been developing a framework for my employer in PHP (their choice, not mine. i wouldn't use it for this if i had the choice but having said that, PHP is not imposing any insurmountable restrictions on us) and when I refactored the class library to use public fields instead of getters/setters, the whole shebang ended up using 25% less memory per request at least.

The __get(), __set() and __call() 'magic' methods really shine for handling interface changes. When you need to migrate a field to a getter/setter (or a getter/setter to a field) they can make the process transparent to any dependent code. With an interpreted language it's a bit harder to find all usages of a field or method even with the reasonably good support for code sensitivity provided by Eclipse PDT or Netbeans, so the magic methods are useful for ensuring that the old interface still delegates to the new functionality.

Say we have an object which was developed using fields instead of getters/setters, and we want to rename a field called 'field' to 'fieldWithBetterName', because 'field' was inappropriate, or no longer described the use accurately, or was just plain wrong. And say we wanted to change a field called 'field2' to lazy load its value from the database because it isn't known initially using a getter...

class Test extends Object {
    public $field;
    public $field2;
}

becomes

class Test extends Object {
    public $fieldWithBetterName = "LA DI DA";
    private $_field2;

    public function getField2() {
        if ($this->_field2 == null) {
            $this->_field2 = CrapDbLayer::getSomething($this->fieldWithBetterName);
        }
        return $this->_field2;
    }

    public function __get($name) {
        if ($name == 'field')) {
            Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
            return $this->fieldWithBetterName;
        }
        elseif ($name == 'field2') {
            Logger::log("use of deprecated property... blah blah blah\n".DebugUtils::printBacktrace());
            return $this->getField2();
        }
        else return parent::__get($name);
    }
}
$t = new Test;
echo $t->field;
echo $t->field2;

(As a side note, that 'extends Object' bit is just a base class I use for practically everything which has a __get() and a __set() declaration which throws an exception when undeclared fields are accessed)

You can go backwards with __call(). This example is quite brittle, but it's not hard to clean up:

class Test extends Object {
    public $field2;

    public function __call($name, $args) {
        if (strpos($name, 'get')===0) {
            $field = lcfirst($name); // cheating, i know. php 5.3 or greater. not hard to do without it though.
            return $this->$field;
        }
        parent::__call($name, $args);
    }
}

Getter and setter methods in PHP are good if the setter has to do something, or if the getter has to lazy load something, or ensure something has been created, or whatever, but they're unnecessary and wasteful if they do nothing other than proxy the field, especially with a few techniques like the ones above to manage interface changes.

Shabbyrobe