SyntaxStudy
Sign Up
PHP Access Modifiers
PHP Beginner 7 min read

Access Modifiers

Access modifiers control the visibility of class properties and methods, enforcing encapsulation — one of the core OOP principles.

  • public — accessible from anywhere.
  • protected — accessible within the class and its subclasses.
  • private — accessible only within the defining class itself.

The default if omitted is public, but always be explicit.

Example
<?php
class BankAccount
{
    private float  $balance;    // no direct access from outside
    protected int  $ownerId;    // accessible in subclasses
    public string  $currency;   // fully public

    public function __construct(int $ownerId, float $initialBalance = 0.0)
    {
        $this->ownerId  = $ownerId;
        $this->balance  = $initialBalance;
        $this->currency = 'USD';
    }

    // Public interface — the only way to interact with balance
    public function deposit(float $amount): void
    {
        if ($amount <= 0) throw new \InvalidArgumentException('Amount must be positive');
        $this->balance += $amount;
        $this->logTransaction('deposit', $amount);
    }

    public function withdraw(float $amount): void
    {
        if ($amount > $this->balance) throw new \RuntimeException('Insufficient funds');
        $this->balance -= $amount;
        $this->logTransaction('withdrawal', $amount);
    }

    public function getBalance(): float
    {
        return $this->balance;
    }

    // Private — internal use only, not part of public API
    private function logTransaction(string $type, float $amount): void
    {
        echo sprintf("[LOG] %s: %.2f %s
", $type, $amount, $this->currency);
    }
}

$account = new BankAccount(1, 100.00);
$account->deposit(50.00);
$account->withdraw(30.00);
echo $account->getBalance(); // 120.00
// $account->balance; // Fatal error — private property
Pro Tip

Tip: Start with the most restrictive visibility (private) and loosen it only when needed. This minimises the public API surface of your class, making it easier to refactor internals without breaking callers.