Visibility decides who is allowed to touch a property or method.
| Keyword | Who can use it |
|---|---|
public | Everyone, from anywhere |
protected | The class itself and classes that extend it |
private | Only the class itself |
<?php
class Account
{
public string $owner = "Ana";
private float $balance = 100;
public function balance(): float
{
return $this->balance;
}
}
$a = new Account();
echo $a->owner . "\n";
echo $a->balance() . "\n";
try {
echo $a->balance;
} catch (Error $e) {
echo $e->getMessage();
}
Ana
100
Cannot access private property Account::$balance
Why hide things
If balance were public, any code could write $a->balance = 1000000;. By making it private, the class controls how the balance changes: only through methods that check the rules.
This idea is called encapsulation: an object protects its own data.
<?php
class Account
{
private float $balance = 0;
public function deposit(float $amount): void
{
if ($amount <= 0) {
throw new InvalidArgumentException("Deposit must be positive.");
}
$this->balance += $amount;
}
public function balance(): float
{
return $this->balance;
}
}
$a = new Account();
$a->deposit(250);
try {
$a->deposit(-50);
} catch (InvalidArgumentException $e) {
echo $e->getMessage() . "\n";
}
echo $a->balance();
Deposit must be positive.
250
Getters and setters
A method that reads a private property is a getter. One that changes it is a setter. They let you add checks.
<?php
class Product
{
private float $price = 0;
public function getPrice(): float
{
return $this->price;
}
public function setPrice(float $price): void
{
if ($price < 0) {
throw new InvalidArgumentException("Price cannot be negative.");
}
$this->price = $price;
}
}
$p = new Product();
$p->setPrice(99.5);
echo $p->getPrice();
99.5
Do not add a getter and a setter for every property out of habit. That is the same as a public property with extra typing. Expose only what outsiders really need. A readonly property (see Properties) is a lighter way to share a value that never changes.
protected: for child classes
<?php
class Shape
{
protected string $name = "shape";
}
class Circle extends Shape
{
public function label(): string
{
return "I am a " . $this->name; // allowed: protected
}
}
echo (new Circle())->label();
I am a shape
Which one should I choose?
- Start with private.
- Make it protected only if a child class needs it.
- Make it public only if outside code must use it.
Methods have visibility too
A private method is a helper that only the class uses.
<?php
class Mailer
{
public function send(string $to): string
{
return $this->format($to);
}
private function format(string $to): string
{
return "To: " . strtolower(trim($to));
}
}
echo (new Mailer())->send(" ANA@EXAMPLE.COM ");
To: ana@example.com