Question

Okay, this is really bugging me and I'm starting to think it all comes down to personal choice rather than a particular way of being more efficient or writing better code: Should I or should I not use getter/setter methods within a PHP project? The answers so far that I've read are rather conflicting and not entirely suited towards PHP, which is not a compiled language. For example, take this question on Stack Overflow ("Why use getters and setters?"). There's a number of good reasons presented as to why I should use them within my code, yet all the child comments mention how Accessors are evil and should be avoided, interspersed between a few more disturbing comments which mention that they should be avoided entirely because it "mucks up your code".

All I'm getting is conflicting answers, none of which are relevant to a interpreted PHP environment. Can someone shine some light on why/why not they should be used within PHP, and their rationale behind that decision? Does it really matter if we can simply define a property as private or protected and, anyway:

The encapsulation getters and setters offer are laughably thin

... quoted from "sbi" (Why use getters and setters?)

Personally, I still don't see how:

Class Foo {
    public $bar;

    function setBarType($val) {
       $this->bar = $val;
    }
}

$fee = new Foo();
$fee->setBarType(42);

is superior to this:

Class Foo {
    public $bar;
}

$fee = new Foo();
$fee->bar = 42;
Was it helpful?

Solution 2

Because if the implementation of how the value is set changes (to a db), you don't have to change the callers. Another example is that you may need to do some checking on the value before setting it.

Having a method lets you intercept the setting/getting of that variable, doing it when it doesn't seem like you need it makes your code more change friendly.

Property getters

Languages like C# and recent versions of JavaScript allow you to intercept property reading and writing, so you can just use properties in languages that support it.

Object watchers

Some languages allow you to intercept the reading/setting of all JavaScript's Object.watch, or inaccessible properties with PHP's __get. This allows you to implements getters and setters but you get a performance hit because of the overhead they create for every property access. This answer talks about other problems with getters and setters. Best practice: PHP Magic Methods __set and __get

Getters and Setters are OK, but...

Just making boilerplate getters and setters is better, but is almost as bad as public properties. If anybody can change your object's state (specially with multiple properties), it won't be well encapsulated. http://cspray.github.io/2012/05/13/stop-calling-them-getters-setters.html

OTHER TIPS

The blog post you linked to starts with a crucial sentence (emphasis added) :

Every getter and setter in your code represents a failure to encapsulate and creates unnecessary coupling.

Encapsulation is the most important idea of Object Oriented Programming. It essentially boils down to hiding complexity by wrapping it neatly inside classes. In an ideal world, when you use a class, you shouldn't have to know anything whatsoever about its inner workings or its state. Some people (like this blog author) will argue that having getters and setters is already way too much information about the insides of the class. In their view, a class should only have methods that enable us to tell an object to do something, never mind how it does it or what state it is in. Using a setter is not "telling the object to do something", it is mucking with the object's state from outside.

Instead of doing this :

$a = myObject();

// Querying object state, making a decision outside the object, and changing its state
if ($a->getWarbleFizz() < 42) {
    $a->setYourWarbleFizzTo(42);
}

// Gee, I hope I made the right decision...
$a->nowDoSomethingUseful();

You should be writing code like this :

$a = myObject(42);
$a->doStuff();

Or this :

$a = myObject();
$a->doStuff(42);

Related reading : Tell, don't ask.

A great profit of using a getter and setter is, whenever you need to make changes you only have to modify the getter and setter.

I'll try to explain with an example:

protected $date;
public function getDate(){
    return $this->date;
}
public function setDate($date){
    $this->date = $date;
}

Imagine there is a reason the date should always be incremented with one day. You will have to search in your entire project where you accessed your class member.

But by using getters and setters you could change the code to:

protected $date;
public function getDate(){
    return $this->date;
}
public function setDate($date){
    $date = new DateTime($date);
    $date->modify('+1 day');
    $this->date = $date;
}

One OOP principe is encapsulation. A class is responsible to all variables that are contained inside this class.

By setting a public variable, you are breaking that principe.

By creating an accessor (setter), you're indirectly breaking that principe by giving a chance for that value to be changed outside of the class.

The advantage of a getter is that the calling method don't need to care about how the data is retrieved. It only know that it will get the expected data and that's all. Here the encapsulation principe is respected.

The advantage of a setter is that the class have the chance to check the new value before applying it. In a perfect world, there is no need for accessors because a class can fully manage all his variables. In the real world, sometimes you need to set a value or get it from the outside.

The best way to approach the perfect world is to limit accesors only to the very few variables that have to be modified. And check setted values if possible.

About your example, the second solution is better because you save one level in the php stack. Your accessor is useless because you variable is public anyway (so, no encapsulation) and don't perform any additionnal check. But when possible, you SHOULD use accessor to check the data. If the data isn't needed anywhere else in your application, then, don't do any accessor.

If you don't use getters and setters in a language like PHP, which is not type safe, then how are you going to ensure the type of the object's property is correct?

I may be missing the point completely, but if you need access to a property from outside of the object, I think it's still the best option to use accessors...

Also, as Juon Mendes mentions: some languages offer you to intercept when the properties themselves are being addressed. This may also be coming to PHP

You could even have a public setter, and a protected getter:

class TimePeriod {
    protected $Seconds = 3600;

    public $Hours {
        get { return $this->Seconds / 3600; }
        set { $this->Seconds = $value * 3600; }
    }

    // This property is read only as there is no setter
    public $Minutes {
        get { return $this->Seconds / 60; }
    }

    /* public getter, protected setter */
    public $Milliseconds {
        get { return $this->Seconds * 1000; }
        protected set { $this->Seconds = $value / 1000; }
    }
}

The choice is up to you. Other important features of PHP 5 to consider are magic getter/setters:

http://www.php.net/manual/en/language.oop5.overloading.php#object.set http://www.php.net/manual/en/language.oop5.overloading.php#object.get

The magic of this is that you are able to do something like the following and decide where to get/set variables without having to declare them beforehand:

Class Foo {
    private $data = array();

    function __set($name,$val) {
       $this->$data[$name] = $val;
    }
    function __get($name) {
       if (array_key_exists($name, $this->data)) {
        return $this->data[$name];
    }
    else {
        return null;
    }
}

Voila, something like this now happens automagically:

$fee = new Foo(); $fee->bar = 42;

IMO using getters and setters is a good practice and increases code readability too. Apart from checking the value while setting, there is another example, consider if u call getMoviesList(). Now this get method can be implemented in anyway, it can get movies list from the local db, get it from the online web service and so on... So the code making the decision maybe inside this function. Wherever u call it from, u don't care about the location and how it gets it. U just get the movies list.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top