LearnContact
Lesson 4319 min read

Access Modifiers

Learn how public, protected, and private control which parts of your code can access a class's properties and methods.

Introduction

So far, every property and method in our examples has been marked `public`, meaning any code anywhere could read or change it directly. Real applications need more control than that. What if a bank account balance could be set to any value by any code that touched the object? Access modifiers exist to prevent exactly that kind of problem.

PHP gives you three access modifiers — `public`, `protected`, and `private` — that control exactly which code is allowed to read or modify a property, or call a method.

What You Will Learn
  • What public, protected, and private mean for properties and methods.
  • A clear summary of which code can access what.
  • Why restricting access improves encapsulation and prevents invalid state.
  • How to use private properties with public getter and setter methods.

The Three Access Modifiers

Every property and method in a PHP class can be marked with one of three visibility keywords.

public

Accessible from anywhere — inside the class, from subclasses, and from outside code.

protected

Accessible from within the defining class and any class that extends it, but not from outside code.

private

Accessible only from within the exact class where it is defined — not even subclasses can reach it.

visibility-basic.php
<?php
class Employee
{
    public string $name;        // anyone can read/write this
    protected float $salary;    // only Employee and its subclasses
    private string $ssn;        // only Employee itself

    public function __construct(string $name, float $salary, string $ssn)
    {
        $this->name = $name;
        $this->salary = $salary;
        $this->ssn = $ssn;
    }
}

$e = new Employee("Priya", 65000, "000-00-0000");
echo $e->name . "\n"; // OK, public
// echo $e->salary; // Error: Cannot access protected property
// echo $e->ssn;    // Error: Cannot access private property
Output
Priya

The commented-out lines would each cause a fatal error if uncommented, because code outside the class has no way to reach a `protected` or `private` member directly.

Visibility Summary Table

ModifierSame ClassSubclassOutside Code
publicYesYesYes
protectedYesYesNo
privateYesNoNo

Read the table left to right for each modifier: `public` is accessible everywhere, `protected` is accessible inside the family of classes (the defining class plus any subclass), and `private` is locked to the exact class that declared it.

Why Restrict Access?

Restricting access is not about hiding information out of secrecy — it is about encapsulation: bundling data together with the only code that is allowed to change it, so the object can guarantee its own rules are never broken.

The Problem Encapsulation Solves

If a property like $balance were public, any code anywhere in a large application could set it to a negative number, a string, or anything else, bypassing every validation rule the class was designed to enforce. By making it private and only changing it through a controlled method, the class can guarantee the balance is always valid.

This matters more as codebases grow. In a small script, a public property is harmless. In a large application maintained by many developers, an object with public properties has no way to protect itself from being put into an invalid state by code written somewhere else entirely.

Worked Example: Getters and Setters

A common pattern is to make a property `private`, then expose controlled access to it through public methods — often called a getter (to read the value) and a setter (to change it, with validation).

bank-account.php
<?php
class BankAccount
{
    private float $balance;

    public function __construct(float $startingBalance = 0.0)
    {
        $this->balance = $startingBalance;
    }

    // Getter: read-only access to the balance
    public function getBalance(): float
    {
        return $this->balance;
    }

    // Setter: controlled, validated way to change the balance
    public function deposit(float $amount): void
    {
        if ($amount <= 0) {
            echo "Deposit must be positive.\n";
            return;
        }
        $this->balance += $amount;
    }

    public function withdraw(float $amount): void
    {
        if ($amount > $this->balance) {
            echo "Insufficient funds.\n";
            return;
        }
        $this->balance -= $amount;
    }
}

$account = new BankAccount(100.0);
$account->deposit(50.0);
$account->withdraw(30.0);
$account->withdraw(1000.0);

echo "Final balance: \${$account->getBalance()}\n";
Output
Insufficient funds.
Final balance: $120

Nothing outside `BankAccount` can touch `$balance` directly — every change is forced through `deposit()` or `withdraw()`, which can reject invalid values. The object protects its own integrity, which is the entire point of encapsulation.

Common Mistakes

Avoid These Mistakes
  • Making every property public "to keep things simple" — this removes all protection against invalid state.
  • Confusing protected with private — protected is still open to subclasses, private is not.
  • Writing a setter that blindly assigns the value without any validation, which defeats the purpose.
  • Forgetting that private properties are invisible even to subclasses, not just to outside code.

Best Practices

  • Default to private for properties, and only widen to protected or public when there is a real reason.
  • Expose state through getter methods rather than public properties, so you can add validation or logic later without breaking callers.
  • Use protected when subclasses genuinely need direct access; otherwise prefer private.
  • Name getters and setters clearly, such as getBalance() and deposit(), rather than generic get()/set().

Frequently Asked Questions

What is the default visibility if I omit a modifier?

If you omit a visibility keyword on a property or method, PHP treats it as public. It is best practice to always write the modifier explicitly.

Can a private property in a parent class be accessed by a subclass?

No. Private members are visible only within the exact class that declares them. A subclass would need the parent to expose it as protected or through a public method.

Do access modifiers apply to methods too, not just properties?

Yes. public, protected, and private work identically on methods, controlling who is allowed to call them.

Is it ever fine to use public properties?

Yes, for simple data-holder objects with no invariants to protect, public properties are reasonable. For anything with rules to enforce, prefer private with controlled access.

Key Takeaways

  • public members are accessible from anywhere.
  • protected members are accessible within the class and its subclasses only.
  • private members are accessible only within the exact defining class.
  • Restricting access enforces encapsulation, preventing invalid state from outside code.
  • A common pattern is a private property paired with public getter and setter methods.

Summary

Access modifiers give you fine-grained control over what code is allowed to touch a class's internals. By defaulting to private and exposing only what is truly needed through public methods, you keep objects in charge of their own valid state — the core idea behind encapsulation.

Lesson 43 Completed
  • You can explain the difference between public, protected, and private.
  • You understand why restricting access improves code safety.
  • You can build a class with private properties and public getters/setters.
Next Lesson →

Inheritance