PHP Access Modifiers: public, protected and private

Access modifiers are easy to understand individually. The interesting part is deciding which one a class member should actually use. Make everything public, and the class soon has no secrets left.

In PHP, public, protected and private control the visibility of class properties, methods and constants. They determine which code can access a member directly.

The basic rule is simple:

  • public members can be accessed from anywhere.
  • protected members can be accessed inside the declaring class and related parent or child classes.
  • private members can be accessed only by the class that declares them.

These visibility rules are a practical part of encapsulation in PHP. They let a class expose the operations other code needs while keeping its implementation details under control.

PHP access modifiers at a glance

Modifier Same class Child class Outside the class
public Yes Yes Yes
protected Yes Yes No
private Yes No No

For most application code, a useful starting point is to keep internal properties and helper methods private. Use protected when subclasses genuinely need access. Make a member public when it is intentionally part of the class interface.

Also, abstract and final are sometimes discussed alongside these keywords, but they are not visibility levels. PHP uses public, protected and private for member visibility.

Public access modifier

A public property or method can be accessed from anywhere that has access to the object. This includes code inside the class, child classes and code outside the class.

Use public for the parts of a class that other code is expected to call directly.

<?php

class User
{
    public string $name;

    public function setName(string $name): void
    {
        $this->name = $name;
    }

    public function getName(): string
    {
        return $this->name;
    }
}

$user = new User();
$user->setName('Vincy');

echo $user->getName();

Both methods are public, so they can be called from outside the class. The property is public too, which means this is also valid:

$user->name = 'John';

echo $user->name;

That flexibility is sometimes useful, but public properties also let outside code change object state directly. In larger classes, keeping important state private and exposing a small public API usually gives you more control.

Private access modifier

A private member can be accessed only from within the class that declares it. Outside code cannot access it directly, and neither can a child class.

This makes private a good default for implementation details that should stay under the class’s control.

<?php

class BankAccount
{
    private float $balance = 0;

    public function deposit(float $amount): void
    {
        if ($amount <= 0) {
            return;
        }

        $this->balance += $amount;
    }

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

$account = new BankAccount();
$account->deposit(500);

echo $account->getBalance();

The balance cannot be changed directly from outside the class. All updates must pass through methods such as deposit(), where the class can validate the value first.

Trying to access the property directly causes an error:

$account->balance = 1000;

PHP reports that the private property cannot be accessed from that context.

Protected access modifier

A protected member sits between public and private. It can be accessed inside the declaring class and by child classes, but not directly from outside the class.

Use protected when a subclass needs access to a property or helper method as part of the inheritance design.

<?php

class Employee
{
    protected string $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }
}

class Manager extends Employee
{
    public function getDisplayName(): string
    {
        return 'Manager: ' . $this->name;
    }
}

$manager = new Manager('Anita');

echo $manager->getDisplayName();

The Manager class can read $name because it inherits from Employee. Code outside the class hierarchy cannot access the property directly.

$manager->name = 'David';

That statement causes an error because $name is protected.

It is tempting to use protected whenever inheritance is involved, but use it carefully. A protected member becomes part of the contract with child classes, which can make future refactoring harder. If a subclass does not need direct access, keep the member private.

Access modifiers with methods

Visibility applies to methods in the same way it applies to properties. Public methods form the callable interface of a class, while protected and private methods are useful for internal work.

<?php

class Order
{
    public function getTotal(float $subtotal): float
    {
        return $this->applyTax($subtotal);
    }

    private function applyTax(float $subtotal): float
    {
        return $subtotal * 1.18;
    }
}

$order = new Order();

echo $order->getTotal(1000);

Outside code can call getTotal(), but it cannot call applyTax() directly. The private method is an implementation detail of the class.

This pattern is useful because it keeps the public API small. Other parts of the application depend only on the methods they actually need, while internal logic remains free to change.

Private and protected members in inheritance

The difference between private and protected becomes most important when PHP inheritance enters the picture.

A child class can access a protected member declared by its parent, but it cannot directly access a private member declared by that parent.

<?php

class Product
{
    private float $costPrice;
    protected float $sellingPrice;

    public function __construct(float $costPrice, float $sellingPrice)
    {
        $this->costPrice = $costPrice;
        $this->sellingPrice = $sellingPrice;
    }
}

class DiscountedProduct extends Product
{
    public function getDiscountedPrice(): float
    {
        return $this->sellingPrice * 0.9;
    }
}

The child class can use $sellingPrice because it is protected. It cannot use $costPrice directly because that property belongs privately to Product.

This is one reason to avoid making members protected without a clear need. Once child classes depend on them, changing their implementation becomes more difficult.

Visibility for class constants

PHP also supports visibility modifiers on class constants. A constant can be public, protected or private.

<?php

class Invoice
{
    public const STATUS_PAID = 'paid';
    protected const TAX_RATE = 0.18;
    private const INTERNAL_CODE = 'INV';
}

A public constant can be accessed from outside the class:

echo Invoice::STATUS_PAID;

The protected and private constants cannot be accessed directly from unrelated outside code.

Constant visibility is useful when a class has fixed values that should be available only to its own implementation or to subclasses.

What happens when no visibility modifier is specified?

For properties and class constants, you should declare the visibility explicitly. For methods, PHP treats a method without a visibility keyword as public by default.

<?php

class Report
{
    function generate(): string
    {
        return 'Report generated';
    }
}

The generate() method is public even though the public keyword is omitted.

Still, writing public explicitly is usually clearer. It makes the intended API obvious when another developer reads the class later.

Can a child class change a member’s visibility?

When overriding an inherited method, a child class can keep the same visibility or make the visibility less restrictive. It cannot make the method more restrictive.

For example, a protected method can become public in the child class:

<?php

class BaseController
{
    protected function formatMessage(string $message): string
    {
        return trim($message);
    }
}

class ApiController extends BaseController
{
    public function formatMessage(string $message): string
    {
        return strtoupper(parent::formatMessage($message));
    }
}

The reverse is not allowed. A child class cannot override a public method and change it to protected or private.

This rule matters because existing code may already depend on the inherited public method. A child class should not silently take that access away.

Access modifiers with constructor property promotion

Visibility also appears in constructor property promotion. In this syntax, the constructor parameter and class property are declared together.

<?php

class Customer
{
    public function __construct(
        private int $id,
        public string $name
    ) {
    }

    public function getId(): int
    {
        return $this->id;
    }
}

$customer = new Customer(101, 'Ravi');

echo $customer->name;
echo $customer->getId();

The $name property is public, so outside code can access it directly. The $id property is private and must be accessed through the class’s public methods.

This compact syntax does not change how visibility works. It only saves you from separately declaring the property and assigning the constructor argument.

How to choose between public, protected and private

The best modifier depends on who genuinely needs access to the member.

  • Use public for methods and values that callers are expected to use.
  • Use protected when child classes need direct access as part of the inheritance design.
  • Use private for implementation details that should remain controlled by the declaring class.

In practice, start with the narrowest visibility that works. It is easy to make a private implementation detail public later. Taking a public member away after other code depends on it is much harder.

Also, do not use private simply to force every property through a getter and setter. Add methods when they protect an invariant, perform validation, calculate something, or provide a meaningful operation. A class filled with mechanical getters and setters can still expose nearly all of its internal state.

Common mistakes with PHP access modifiers

Most visibility errors are straightforward once you know which class owns the member.

Accessing a private property from outside the class

<?php

class UserProfile
{
    private string $email = 'user@example.com';
}

$profile = new UserProfile();

echo $profile->email;

This fails because $email is private. Expose a public method if outside code genuinely needs the value.

Accessing a private parent member from a child class

<?php

class ParentClass
{
    private string $message = 'Hello';
}

class ChildClass extends ParentClass
{
    public function showMessage(): string
    {
        return $this->message;
    }
}

The child class cannot directly access $message. If subclasses should use the member, make it protected or provide a protected/public method in the parent class.

Making too much state public

A public property lets any caller change it directly. That can bypass validation and leave an object in an invalid state.

For example, an account balance usually should not be changed like this:

$account->balance = -5000;

A method such as withdraw() gives the class a place to enforce its own rules before changing the balance.

Are abstract and final access modifiers?

No. abstract and final affect inheritance and overriding, not visibility.

An abstract method defines a method that a concrete child class must implement. A final method prevents child classes from overriding it. A final class cannot be extended.

<?php

abstract class PaymentGateway
{
    abstract public function pay(float $amount): bool;

    final protected function logPayment(float $amount): void
    {
        // Internal logging logic.
    }
}

Notice that abstract and final can appear together with visibility modifiers. In this example, public and protected control access, while abstract and final control inheritance behavior.

PHP access modifiers summary

PHP uses three visibility levels for class members: public, protected and private.

  • public exposes a member everywhere.
  • protected keeps it inside the class hierarchy.
  • private keeps it inside the declaring class.

Choose visibility based on the smallest audience that actually needs access. That keeps the public API easier to understand and gives the class more freedom to change internally later.

Photo of Vincy, PHP developer
Written by Vincy Last updated: August 14, 2026
I'm a PHP developer with 20+ years of experience and a Master's degree in Computer Science. I build and improve production PHP systems for eCommerce, payments, webhooks, and integrations, including legacy upgrades (PHP 5/7 to PHP 8.x).

Continue Learning

These related tutorials may help you continue learning.

6 Comments on "PHP Access Modifiers: public, protected and private"

Leave a Reply

Your email address will not be published. Required fields are marked *

Explore topics
Need PHP help?