We use cookies and similar technologies to enhance your browsing experience, analyze site traffic, and personalize content. You can customize your preferences at any time.
Manage your cookie consent preferences.

These cookies are essential for the proper functioning of our website. They enable core functionality such as page navigation, access to secure areas, and basic user interface features.

These cookies enable the website to provide enhanced functionality and personalization. They may be set by us or by third-party providers whose services we have added to our pages.

These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us to know which pages are the most and least popular and see how visitors move around the site.

These cookies are used to deliver advertisements that are more relevant to you and your interests. They are also used to limit the number of times you see an advertisement and help measure the effectiveness of advertising campaigns.

development environment

Asymmetric Visibility: True Data Immutability Natively

The PHP ecosystem has quieted the noise of the past by consistently delivering rapid, engineering-focused evolutionary steps. As we navigate 2026, the language powers a vast majority of the modern web, serving as a robust foundation for enterprise-grade applications. With the release of PHP 8.4, the language has introduced engine-level modernity that fundamentally changes how we design object-oriented systems.

One of the most profound shifts in this release addresses a core pillar of Domain-Driven Design (DDD) and clean software architecture: data encapsulation and immutability. By introducing Asymmetric Visibility (public private(set) constructs), PHP 8.4 allows developers to achieve true data immutability natively within the engine, completely eliminating historical boilerplate.

The Legacy Way: Manual Encapsulation and Boilerplate Overload

Historically, PHP objects required exhaustive boilerplate code for data encapsulation—endless getters, setters, and manual validation. If you wanted to build a clean Domain-Driven Design (DDD) Value Object or Entity, you had to write lines of defensive code just to protect your object's internal state.

Before PHP 8.4, enforcing data integrity or formatting data upon access required explicit methods. To make a property read-only outside the class but modifiable from within, developers had to resort to making properties private or protected and writing public "getter" methods.

php
1// The Pre-PHP 8.4 Manual Approach
2class Invoice {
3 private string $id;
4 private float $amount;
5 
6 public function __construct(string $id, float $amount) {
7 $this->id = $id;
8 $this->amount = $amount;
9 }
10 
11 // Public getters to allow reading
12 public function getId(): string {
13 return $this->id;
14 }
15 
16 public function getAmount(): float {
17 return $this->amount;
18 }
19 
20 // Internal logic modifying state requires explicit methods
21 public function applyDiscount(float $discount): void {
22 $this->amount -= $discount;
23 }
24}

This approach works, but it is noisy. The actual architectural purpose of the object is drowned out by syntax noise. While PHP 8.1 introduced readonly properties, they came with a strict limitation: once initialized, they could never be changed—even from within the class itself. This made readonly ideal for completely immutable value objects but entirely unsuited for entities requiring internal state updates.

The Modern Approach: Asymmetric Visibility

PHP 8.4 solves this architectural dilemma by separating read visibility from write visibility natively at the engine level. By using the public private(set) syntax, a property can be read freely from any scope but can only be modified from within the class that defines it.

Let’s look at how this simplifies an enterprise-grade Invoice object when paired with Constructor Property Promotion:

php
1// Modern PHP 8.4+ Implementation
2class Invoice {
3 public function __construct(
4 public private(set) string $id,
5 public private(set) float $amount
6 ) {}
7 
8 public function applyDiscount(float $discount): void {
9 // Legal: Internal mutation is allowed
10 $this->amount -= $discount;
11 }
12}
13 
14// Client Code Usage
15$invoice = new Invoice('INV-2026-001', 500.00);
16 
17// Legal: Public reading is natively permitted without a getter method
18echo $invoice->amount; // Outputs: 500.00
19 
20// Error: Fatal error: Cannot modify private(set) property Invoice::$amount from global scope
21$invoice->amount = 100.00;

Combining Asymmetric Visibility with Property Hooks

To take data safety a step further, PHP 8.4 allows us to pair Asymmetric Visibility with another groundbreaking engine feature: Property Hooks. Property Hooks allow us to define get and set operations directly on the property declaration.

This enables true data immutability natively, ensuring properties can be read publicly but only modified internally or through strict engine boundaries. We can even create virtual properties that are computed dynamically on demand through a get hook, meaning they do not even exist as a standard state property in memory.

php
1class AdvancedInvoice {
2 public function __construct(
3 public private(set) string $id,
4 private float $subtotal,
5 private float $taxRate
6 ) {}
7 
8 // A virtual, read-only property computed dynamically on demand
9 public private(set) float $total {
10 get => $this->subtotal * (1 + $this->taxRate);
11 }
12}

Why This Wins the Backend Battle

Shifting data protection from userland PHP code directly into the engine core provides significant engineering advantages:

  1. Massive Memory & Performance Optimizations: By keeping data access structures native to the engine rather than routing them through userland PHP methods (like manual getters), the engine optimizes memory execution pathways.

  2. Elimination of Static Noise: Codebases become strictly expressive. Your entities represent your domain logic, not your language's syntax limitations.

  3. Seamless Tooling Integration: Modern static analysis suites like PHPStan and Psalm parse asymmetric visibility and property hook definitions natively, preventing type and visibility conflicts before execution ever hits production.

Modern PHP is robust, lightning-fast, highly structured, and optimized for cloud-native environments. The conversation has evolved. The modern PHP ecosystem isn't focused on looking back at where the language was—it is actively building where backend engineering is going.

External Sources & Further Reading

  • Posted on: May 27th, 2026
  • By: Darren Odden
  • On: Blog
  • php
  • asymmetric visibility

Share this on social media

About the author

Muppet Darren.

Darren Odden

Built for Developers, by Developers

Join the movement and discover why modern PHP is the sophisticated choice for elegant, high-scale applications in 2026.

Home

Policy

Reach Us

©2026 doPHP.dev