There are a few schools of thought on getters/setters. However, they’re a necessary evil. The biggest advantage of getters is futureproofing.
Consider the following class:
class Product {
public $price;
}
You have various bits of code that use price e.g.
'The price of the product is' . $procuct->price;
$total = $product->price * $quantity;
If the requirements change and now product prices must include tax at 20% then you have a problem. If you’d used a getter, e.g.
class Product {
private $price;
public function getPrice() {
return $this->price;
}
}
Then the change is a 30 second job:
class Product {
private $price;
public function getPrice() {
return $this->price * 1.2;
}
}
Bertrand Meyer (One of the pioneers of OOP) coined the Uniform Access Principle which states that “Someone using the class should not know whether a value is calculated or stored by the class”.
So that’s why you should use getters and setters. However, a bigger question that’s harder to answer is: When should you use getters and setters?
Are they always necessary? Well, often not as explicitly as you’d think. Consider again this example:
$total = $product->getPrice() * $quantity;
Seems reasonable? Think again. Here encapsulation has been broken. Encapsulation has been defined as
Encapsulation is the packing of data and functions into a single component.
Clearly, in this example the data is being worked on in a function outside the class!
When is this a problem? Well it’s inflexible. The same rule is applied to every product, I’ve worked on e-commerce sites where products have bands (Buy 10 and the unit price goes down by 5%, buy 100 and the unit price goes down by 10%, etc, of course this could be different for different products).
Instead, consider moving the behaviour that uses the data into the class itself:
class Product {
private $price;
public function calculatePrice($quantiy) {
if ($quantity < $this->band1) $unitprice = $this->price;
else if ($quantity > $this->band1) $unitprice = $this->price * $this->discount1;
else if ($quantity > $this->band2) $unitprice = $this->price * $this->discount2;
return $unitprice * $quantity;
}
}
Here the calculation has been moved into the product class (Proper encapsulation) and the need for a simple getter that just returns $this->price has been removed entirely.