---
title: "Asymmetric visibility for PHP properties"
url: https://www.exakat.io/asymmetric-visibility-for-php-properties/
date: 2024-10-15
modified: 2024-10-15
author: "dams"
description: "[caption id=\"attachment_15260\" align=\"alignleft\" width=\"300\"] Asymmetric visibility for PHP property[/caption] Asymmetric visibility for PHP properties One of the lesser visible feature coming to PHP 8.4, pun intended, is the assymetric visibility..."
categories:
  - "Code auditing"
image: https://www.exakat.io/wp-content/uploads/2024/10/paint.320.jpg
word_count: 1248
---

# Asymmetric visibility for PHP properties

[![Asymmetric visibility for PHP property](https://www.exakat.io/wp-content/uploads/2024/10/paint.320-300x300.jpg)](https://www.exakat.io/wp-content/uploads/2024/10/paint.320.jpg)Asymmetric visibility for PHP property

# Asymmetric visibility for PHP properties

One of the lesser visible feature coming to PHP 8.4, pun intended, is the assymetric visibility for PHP properties. It is an upgrade of the current visibility, and also, a number of refined features over readonly, properties hooks or magic methods. It is not for everyone, but it might be quite useful. Let's take a look!

## Asymmetric Visibility

Personnally, I didn't know that visibility was symmetric. How can `public`, `protected` and `private` have some symmetry? It actually boils down to read and write. A property is both `private` for reading and writing. That's all.

Here, the public property acts as a rustic getter/setter (or lack of). It makes sens for `$side`, but it is more awkward for the `$area` property, which should actually be readable from anywhere, but writeable only with `$side`.

For PHP 8.4, Ilija Tovilo and Larry Garfield, are now introducing a new visibility setting for writing. Literally, a `set` visibility: `private(set)`.

With this new setting, the `$area` property may be read with `public` visibility: a.k.a., everywhere. And it can only set with `private` visibility: a.k.a. from inside the class. Here, it is the constructor. Et voila!

The read and write visibilities are now asymmetric, as they do not have the same scope of application.

## Which visibilities for which properties?

With now 2 sets of visibilities, PHP is introducing no less than 9 different configurations of visibilities. This is quite a lot, in fact, and it seems it is going to make the visibility declaration harder to read. But, don't get scared, there are some classic user-friendliness down the road.

So, let's see if we can get a better understanding of all these visibilities.

### The three symmetric visibilities

First, let's see the symmetric visibilities. After all, `private private(set)`, `protected protected(set)` and `public public(set)` are the symmetric visibilities. We have had them ever since the conception of PHP (or almost... sorry Rasmus), and we already have a nice short hand to write them : `private`, `protected`, `public`. So, no change for these: keep them short and backward compatible!

Also, the new token `private(set)` (and its cousins), are an addition to the language. This means they can be used alone, without the classic read visibilities. And, what happens when the visibility is omitted? It is by default `public`. This behavior also stays in PHP 8.4, even when setting explicitely the asymmetric visibility.

### The three asymmetric visibilities

The three asymmetric visibilities are the following : `public private(set)`, `protected private(set)` and `public protected(set)`. These are not symmetric (see above), and they provide a distinct scope for reading (`public`), and one for writing (`private(set)`. This is the example we had with the initial `Square` class.

### The three illegal visibilities

The last three asymmetric visibilities are the following : `private public(set)`, `private protected(set)` and `protected public(set)`. These are the last, where the host class cannot write its properties, but can get them written from everywhere in the application. All these make little sense, and are forbidden by PHP.

For those of you who have used writeable-only files on the system, the comparison is not straightforward. While writing in a file where one can't read is a valid usage on the OS (think, logs, which are read elsewhere), this is not applicable for an object. It would be easy to circumvent this limitation and access the property anyway.

### Syntax summary

| | | private | protected | public | |
| --- | --- | ------- | --------- | ------ | --- |
| | **private(set)** | Sym. | Illegal | Illegal | |
| | **protected(set)** | Useful | Sym. | Illegal | |
| | **public(set)** | Useful | Useful | Sym. | |

# A few precautions

## Asymmetry also for static properties

Static properties also support asymmetric visibility.

Note that the RFC mentions that static properties would not be covered, but a few manual tests showed that it is not the case.

## Only for typed properties

Asymmetric visibility is only for typed properties. It's another compile-time syntax error.

## The PHP 8.3 error message

Obviously, this new syntax is not backward compatible. This means that, once you have adopted the asymmetric visibilities, it is not possible to go back to PHP 8.3 or older. The error message is actually intriguing:

Yes, PHP doesn't allow the multiplication of `private private private $property` and tell you about it. This check was introduced in PHP 5.3: then, you could make properties really really private by repeating the keyword. That 'feature' was removed in modern versions of PHP, for the better of everyone.

## private(set), case insensitive and no space

The final funny aspect of this new token is its syntax constraints. It is a PHP keyword, and as such, is case insensitive. Hugh, UPPERCASE KEYWORDS...

On the other hand, it doesn't tolerate any space anywhere, or it yields a PHP 8.3 error message. Nothing difficult to remember. Yet, when one is accustomed to the white-space flexibility of the append operator, it is difficult not to regret it.

## A RFC worth reading

There is a lot more to mention about the asymmetric visibility, in particular its relationship with [references](https://wiki.php.net/rfc/asymmetric-visibility-v2#references), [objects](https://wiki.php.net/rfc/asymmetric-visibility-v2#object_properties), and [arrays](https://wiki.php.net/rfc/asymmetric-visibility-v2#array_properties), and [readonly](https://wiki.php.net/rfc/asymmetric-visibility-v2#relationship_with_readonly), and, obviously, with the upcoming [property hooks](https://wiki.php.net/rfc/asymmetric-visibility-v2#interaction_with_property_hooks), and [inheritance](https://wiki.php.net/rfc/asymmetric-visibility-v2#inheritance), and [sentinel data](https://wiki.php.net/rfc/asymmetric-visibility-v2#readonly_cannot_use_a_custom_sentinel), etc.

This is too long to write here, and also, the [RFC is extremely well written](https://wiki.php.net/rfc/asymmetric-visibility-v2) and detailled. Take a look at it, and then, thank [Ilija](https://phpc.social/@ilutov) and [Larry](https://phpc.social/@Crell) for the hard work they put in this new PHP gem.

## Until then, happy auditing!

In the mean time, give a try to the new asymmetric visibility for PHP properties and its new syntax with your own [download of the PHP 8.4](https://www.php.net/archive/2024.php#2024-10-10-1), for testing purposes, or online with [3v4l.org](https://3v4l.org/#live) (select git.master as PHP 8.4 version).