Skip to main content

Encapsulation

Encapsulation is one of the Four Pillars of OOP.

The four pillars are:

  1. Encapsulation
  2. Inheritance
  3. Polymorphism
  4. Abstraction

Encapsulation is probably one of the most important concepts because it protects object data and prevents invalid states.


What is Encapsulation?

Encapsulation means:

Bundling data and methods together while hiding internal implementation details.

Or simply:

Protect object data from direct modification.

Real Life Example

Think of a car.

You accelerate using:

Pedal

You do NOT directly modify:

Engine RPM
Fuel Injection
Air Intake

Those internal details are hidden.

This is encapsulation.


Bank Example

Imagine if everyone could directly modify bank balances.

Bad:

$account->balance =
1000000000;

Anyone could become rich instantly.

Encapsulation prevents this.


Without Encapsulation

class Player {

public int $money = 0;

}

Usage:

$player->money =
-500000;

Invalid state.


Another example:

$player->money =
999999999999999999;

Game economy breaks.


Why Encapsulation Exists

To protect:

✅ Data Integrity

✅ Validation Rules

✅ Security

✅ Maintainability


Proper Encapsulation

class Player {

private int $money = 0;

}

Now:

$player->money

produces an error.


Visualization

Outside World

Public Methods

Private Data

Getters and Setters

Encapsulation is usually implemented using:

  • Getters
  • Setters

Getter

Returns data.

public function getMoney()
: int {

return $this->money;

}

Usage:

echo
$player->getMoney();

Setter

Modifies data.

public function setMoney(
int $money
): void {

$this->money =
$money;

}

Usage:

$player->setMoney(
5000
);

Why Setters are Useful

Because validation can be added.

Example:

public function setMoney(
int $money
): void {

if (
$money < 0
) {
return;
}

$this->money =
$money;

}

Negative values are prevented.


Validation Example

class Player {

private int $health = 20;

public function setHealth(
int $health
): void {

if (
$health < 0
) {
$health = 0;
}

if (
$health > 20
) {
$health = 20;
}

$this->health =
$health;

}

}

Benefits of Encapsulation


1. Data Protection

Nobody can directly modify internals.


2. Validation

Ensure valid data.


3. Easier Maintenance

Internal implementation can change.

External code remains unchanged.


4. Security

Sensitive information stays hidden.


Example

Bad:

public string $password;

Good:

private string $password;

Real World Example

User class:

class User {

private string $password;

}

Methods:

setPassword()
verifyPassword()

Nobody should access raw password.


Example

class User {

private string $password;

public function setPassword(
string $password
): void {

$this->password =
password_hash(
$password,
PASSWORD_DEFAULT
);

}

}

This is encapsulation.


Data Hiding

Encapsulation is sometimes called:

Data Hiding

because internal state becomes hidden.


Visualization

Player

├── private money
├── private health

├── public getMoney()
├── public addMoney()
└── public damage()

Read-Only Data

Sometimes we only want reading.

Example:

private string $uuid;

Getter:

public function getUuid()
: string {

return $this->uuid;

}

No setter.

Now UUID cannot change.


Immutable Objects

Another approach:

readonly

Example:

public readonly string $uuid;

Encapsulation Example

class BankAccount {

private float $balance = 0;

public function deposit(
float $amount
): void {

if (
$amount <= 0
) {
return;
}

$this->balance +=
$amount;

}

public function withdraw(
float $amount
): void {

if (
$amount >
$this->balance
) {
return;
}

$this->balance -=
$amount;

}

public function getBalance()
: float {

return $this->balance;

}

}

PocketMine Example

Simplified Player:

class Player {

private int $health = 20;

public function getHealth()
: int {

return $this->health;

}

public function setHealth(
int $health
): void {

if (
$health < 0
) {

$health = 0;

}

$this->health =
$health;

}

}

Why Not Public?

Bad:

$player->health =
-9999;

Could crash plugins.


Encapsulation in APIs

API Response:

$user->getName();

You don't know where name comes from:

  • Database
  • Cache
  • File
  • Redis

Implementation remains hidden.


Internal Implementation Can Change

Today:

return $this->money;

Tomorrow:

return
$this->wallet
->getBalance();

Outside code remains same.

This is extremely powerful.


Encapsulation and Dependency Injection

private Database $database;

Expose only required methods.

Never expose database connection publicly.


Enterprise Example

UserService

Repository

Database

Everything remains encapsulated.


Real PocketMine Architecture

Player

├── private NetworkSession
├── private Inventory
├── private Effects
├── private Metadata

├── public sendMessage()
├── public teleport()
└── public kick()

Internals remain hidden.


Common Beginner Mistakes


Making Everything Public

Bad:

public int $money;

Creating Useless Getters

Bad:

getMoney()
setMoney()

without validation.


Exposing Sensitive Data

Bad:

public string $password;

Returning Mutable Objects

Example:

return $this->inventory;

External code may modify it unexpectedly.


Best Practices

✅ Keep properties private.

✅ Expose only required methods.

✅ Validate all data.

✅ Hide implementation details.

✅ Protect sensitive information.


Rule of Thumb

Private by Default

Only expose what is necessary.


Exercises


Exercise 1

Create:

class Player {

private int $money = 0;

}

Add:

addMoney()
removeMoney()
getMoney()

Exercise 2

Create:

BankAccount

Prevent negative balances.


Exercise 3

Create password setter using:

password_hash()

Mini Project

Create:

PlayerProfile

Properties:

uuid
name
rank
coins
kills
deaths

Use proper encapsulation.


Quiz

What is Encapsulation?

Answer

Hiding internal implementation and protecting object data.


Which visibility is commonly used?

Answer
private

Why are setters useful?

Answer

They allow validation.


Why should passwords never be public?

Answer

Sensitive information must remain hidden.


Summary

Encapsulation provides:

✅ Security

✅ Validation

✅ Maintainability

✅ Better Architecture

✅ Data Integrity


References

https://www.php.net/manual/en/language.oop5.visibility.php

https://www.php.net/manual/en/language.oop5.properties.php


Next Chapter

➡ Inheritance

➡ Polymorphism

➡ Abstraction