Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A protected property in PHP is a class member variable defined with the protected access modifier, restricting its visibility strictly to the declaring class and any classes that inherit from it (subclasses). It cannot be accessed or mutated directly from outside the class hierarchy via an object instance.

Syntax

Protected properties are declared using the protected keyword. As of PHP 7.4, they fully support type declarations.
class BaseClass {
    protected $untypedProperty;
    protected string $typedProperty = 'default_value';
}

Visibility and Access Rules

The PHP engine enforces the following scope resolution rules for protected properties:
  1. Declaring Class: Full read/write access via $this->propertyName.
  2. Subclasses (Child Classes): Full read/write access via $this->propertyName.
  3. Same-Type Object Access: Objects within the same inheritance hierarchy can access each other’s protected properties. A method belonging to a class in the hierarchy can access $otherInstance->propertyName directly, provided $otherInstance is an object of a class within that same hierarchy.
  4. Global Scope / External Context: Access is denied. Attempting to read or write a protected property from an external context results in a Fatal error: Uncaught Error: Cannot access protected property.

Mechanical Example

The following code demonstrates the inheritance mechanics, including the cross-instance access boundaries of a protected property:
class ParentClass {
    protected string $data = 'Base Data';

    public function copyFrom(ParentClass $otherInstance): void {
        // Valid: Accessing a protected property of another instance 
        // because the method is executing within the allowed class hierarchy.
        $this->data = $otherInstance->data;
    }
}

class ChildClass extends ParentClass {
    public function modifyData(string $newData): void {
        // Valid: Subclass accessing the inherited protected property
        $this->data = $newData;
    }

    public function retrieveData(): string {
        // Valid: Subclass reading the inherited protected property
        return $this->data;
    }
}

$instanceA = new ChildClass();
$instanceB = new ChildClass();

$instanceA->modifyData('Updated Data');
$instanceB->copyFrom($instanceA);

echo $instanceB->retrieveData(); // Outputs: Updated Data

// Invalid: Direct access from the global scope throws a Fatal Error
// echo $instanceA->data; 
// $instanceA->data = 'New Data';

Technical Characteristics

Visibility Widening (Overriding) When a subclass overrides a protected property, PHP’s inheritance rules dictate that the visibility can be maintained or widened, but never restricted. A subclass can redeclare a protected property as public, but attempting to redeclare it as private will trigger a Fatal Error.
class A {
    protected int $counter = 0;
}

class B extends A {
    // Valid: Widening visibility to public
    public int $counter = 0; 
}

class C extends A {
    // Fatal error: Access level to C::$counter must be protected (as in class A) or public
    // private int $counter = 0; 
}
Static Protected Properties The protected modifier can be combined with the static keyword. The same visibility rules apply, but the property belongs to the class itself rather than an instance. It is accessed using the scope resolution operator (::) via self::$property, parent::$property, or static::$property (for Late Static Binding).
class Base {
    protected static int $count = 10;
}

class Child extends Base {
    public static function getCount(): int {
        return static::$count;
    }
}
Reflection API Bypass While the PHP engine strictly enforces protected visibility during standard execution, the Reflection API can bypass these restrictions at runtime. As of PHP 8.1, protected properties are accessible by default when using ReflectionProperty::getValue() or ReflectionProperty::setValue(). The previously required setAccessible(true) method call is now a no-op and is no longer necessary to interact with protected members via Reflection.
Master PHP with Deep Grasping Methodology!Learn More