An Overview of “Getter and Setter” Usage in Modern Object Oriented PHP
Posted by
admin
Wednesday March
4th
, 2026 8:45
a.m.
This is one of those OOP topics that sounds simple but has real architectural implications.
I’ll frame this specifically for modern PHP (8.x style).
1️⃣ What Are Getters and Setters?
In OOP, a getter reads a property.
A setter writes (modifies) a property.
Without getters/setters
class User {
public string $email;
}
$user = new User();
$user->email = "test@example.com";
echo $user->email;
Here, $email is public — anyone can change it to anything.
With getters/setters
class User {
private string $email;
public function getEmail(): string {
return $this->email;
}
public function setEmail(string $email): void {
$this->email = $email;
}
}
Now access is controlled.
2️⃣ Why Were They Created?
Originally, getters/setters were used to support:
✅ 1. Encapsulation (Core OOP principle)
You hide internal state and control access.
Instead of:
$user->email = "invalid";
You can enforce rules:
public function setEmail(string $email): void {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException("Invalid email");
}
$this->email = $email;
}
Now the object protects itself.
✅ 2. Future-proofing
Maybe today $email is stored directly.
Tomorrow you want to:
- Normalize case
- Log changes
- Trigger an event
- Hash something
- Derive value dynamically
If you used a getter/setter, you don’t break your public API.
✅ 3. Derived values
public function getFullName(): string {
return $this->firstName . ' ' . $this->lastName;
}
No actual property — just computed logic.
3️⃣ Why Do People Say Getters/Setters Are Bad?
Because they are often misused.
🚫 The “anemic object” problem
If your class looks like this:
class User {
private string $email;
public function getEmail(): string { return $this->email; }
public function setEmail(string $email): void { $this->email = $email; }
}
Then your object is just a data container.
All logic lives elsewhere.
This is basically procedural programming disguised as OOP.
🚫 They break encapsulation if they just expose everything
If every private property has:
- a getter
- a setter
Then it’s effectively public.
You didn’t gain much.
4️⃣ Modern PHP Best Practice (PHP 8.x)
This is where things get interesting.
🧠 Best Practice Philosophy
👉 Only add a setter if it makes sense for the domain.
👉 Many objects should be immutable.
5️⃣ The Better Pattern: Constructor + No Setters
Instead of:
$user = new User();
$user->setEmail("test@example.com");
Prefer:
class User {
public function __construct(
private string $email
) {
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
throw new InvalidArgumentException();
}
}
public function getEmail(): string {
return $this->email;
}
}
Now:
- Object is valid from birth
- Cannot enter invalid state
- Safer in larger systems
- Easier to reason about
This is common in:
- Domain-Driven Design
- Event-driven systems
- Modern Laravel/Symfony apps
6️⃣ When Should You Use Setters?
Use setters when:
✅ 1. The property is truly changeable
Example:
- User can change email
- Order can change status
- Profile can update bio
But even then — prefer behavior methods:
Instead of:
$order->setStatus("shipped");
Better:
$order->markAsShipped();
That’s expressive and domain-driven.
✅ 2. You’re working with frameworks that require them
Some ORMs (like Doctrine) or serializers sometimes expect getters/setters.
But even modern frameworks support constructor-based injection now.
7️⃣ When Should You Avoid Setters?
Avoid them when:
- The value should never change (ID, creation date)
- It would allow invalid object states
- You’re just adding them “because that’s what OOP does”
8️⃣ The Real Principle Behind This
This is the deeper idea:
Objects should protect their invariants.
If a setter allows the object to become invalid, it’s a bad setter.
Example of dangerous setter:
$user->setAge(-10);
Better:
public function celebrateBirthday(): void {
$this->age++;
}
That enforces real-world logic.
9️⃣ The Modern PHP Summary
❌ Old-school approach
- Private properties
- Getter + setter for everything
✅ Modern approach
- Constructor injection
- Immutable objects where possible
- Behavior-driven methods
- Minimal setters
- Protect invariants
10️⃣ Simple Rule of Thumb
Ask yourself:
“Does this object need to allow this value to change?”
If yes → maybe a setter
If no → constructor only
If it’s business behavior → use a method like approve(), publish(), cancel()
If you’d like, I can:
- Show you a “bad OOP PHP example”
Then refactor it into a clean modern design