> ## 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.

# PHP Readonly Property

A readonly property in PHP is a class property that can be initialized exactly once. After initialization, its value becomes immutable for the lifecycle of the object, and any subsequent attempt to modify or unset it will result in a fatal `Error`.

## Syntax and Initialization

The `readonly` modifier is applied to a property declaration. It can be used alongside visibility modifiers (`public`, `protected`, `private`).

```php theme={"dark"}
class Configuration {
    public readonly string $environment;

    public function __construct(string $environment) {
        // First initialization is legal
        $this->environment = $environment; 
    }
}
```

It is frequently combined with constructor property promotion for brevity:

```php theme={"dark"}
class Configuration {
    public function __construct(
        public readonly string $environment
    ) {}
}
```

## Strict Technical Constraints

**1. Explicit Typing Requirement**
A readonly property must have an explicit type declaration. Untyped properties cannot be marked readonly. If any type is acceptable, the `mixed` type must be explicitly declared.

```php theme={"dark"}
class InvalidExample {
    public readonly $untyped; // Fatal error: Readonly property must have type
}
```

**2. Scope of Initialization**
A readonly property can only be initialized from within the scope of the class where it is declared. It cannot be initialized from outside the class, even if the property is `public`.

```php theme={"dark"}
class State {
    public readonly string $status;
}

$state = new State();
// Error: Cannot initialize readonly property State::$status from global scope
$state->status = 'active'; 
```

**3. Static Modifier Prohibition**
Readonly properties cannot be declared as `static`. The `readonly` modifier is strictly tied to instance properties. Attempting to combine them results in a fatal error.

```php theme={"dark"}
class InvalidStatic {
    public static readonly int $value; // Fatal error: Cannot use the static modifier on a readonly property
}
```

**4. No Default Values**
Readonly properties cannot specify a default value in their declaration. A default value constitutes an initialization, which would permanently lock the property to that value for all instances.

```php theme={"dark"}
class InvalidDefault {
    public readonly int $status = 1; // Fatal error: Readonly property cannot have default value
}
```

**5. Unsetting is Prohibited**
Once initialized, a readonly property cannot be destroyed using `unset()`.

```php theme={"dark"}
unset($config->environment); // Error: Cannot unset readonly property
```

**6. Pass-by-Reference Restriction**
Readonly properties cannot be passed by reference to functions or methods, as this would create a vector for bypassing the immutability constraint.

```php theme={"dark"}
array_pop($this->readonlyArrayProperty); // Error: Cannot pass readonly property by reference
```

## Shallow Immutability

The `readonly` modifier enforces a strict binding between the property and its assigned value. However, if the assigned value is an object, the internal state of that referenced object remains mutable. The readonly constraint prevents assigning a *new* object to the property, but does not make the referenced object itself immutable.

```php theme={"dark"}
class Container {
    public function __construct(
        public readonly stdClass $data
    ) {}
}

$container = new Container(new stdClass());
$container->data->key = 'value'; // Legal: Mutating the referenced object's internal state
$container->data = new stdClass(); // Error: Cannot reassign the readonly property itself
```

## Readonly Classes (PHP 8.2+)

The `readonly` modifier can be applied to the class declaration itself. This implicitly marks every declared property within the class as `readonly` and prevents the creation of dynamic properties.

```php theme={"dark"}
readonly class User {
    public string $username; // Implicitly readonly
    public int $id;          // Implicitly readonly
}
```

## Reinitialization during Cloning (PHP 8.3+)

As of PHP 8.3, readonly properties can be reinitialized exclusively within the `__clone()` magic method. This allows for deep cloning of objects containing readonly properties.

```php theme={"dark"}
class Document {
    public function __construct(
        public readonly DateTime $createdAt
    ) {}

    public function __clone() {
        // Legal in PHP 8.3+: Reinitializing during clone
        $this->createdAt = clone $this->createdAt; 
    }
}
```

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor PHP Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
