PHP, what are dynamic properties?
These days we hear a lot about dynamic properties in PHP and the possibility of it being deprecated by version 8.2, only to disappear from version 9.
The proposal is documented in a dedicated RFC https://wiki.php.net/rfc/deprecate_dynamic_properties, and it generated a lot of discussion specially on the social networks (like twitter etc.).
What are dynamic properties?
A property is an attribute/variable declared in a class. For example, $name is a property for class User. We can declare $name at the beginning of the class, and we can declare the visibility (in this case public) and we may declare the type of the property (in this case string):
class User {
public string $name;
}
In the methods of the class, we can access to the declared property:
class User {
public string $name; public function __construct($name="") {
$this->name = $name;
}
}
Dynamic properties are property that are not declared in the class, but in the code in your class, you want to use a not declared property:
class User {
public string $name; public function __construct($name="", $age = 0) {
$this->name = $name;
// Assigns the not existent property age
$this->age = $age;
}
}
In the example above, in the constructor method I accessed the age property, through $this->age. In this case PHP will create dynamically the property.
An example with dynamic property
class User {
public string $name;public function __construct($name="", $age = 0) {
$this->name = $name;
// Assigns the not existent property age
$this->age = $age;
}
}$user = new User;
// Assigns declared property User::$name.
$user->name = "foo";// Oops, a typo:
$user->nane = "foo";
// PHP <= 8.1: Silently creates dynamic $user->nane property.
// PHP 8.2: Raises deprecation warning, still creates dynamic property.
// PHP 9.0: Throws Error exception.
echo $user->nane;
This example taken from https://wiki.php.net/rfc/deprecate_dynamic_properties and modified to add age parameter to show an example with a typo while you are accessing to the property. This is a “hidden” bug, because you think that you performed a correct assignment but at the end you have an unexpected behavior because of the typo (nane instead of name).
With the PHP 8.0 and 8.1, PHP will create a dynamic property named nane.
With PHP 8.2 you have a warning during the execution, but the dynamic property is created.
With PHP 9.0 you will have an exception.
What can you do today?
My strong suggestion is to use a code static analysis tool like PHPstan or Psalm.
With PHPstan you can execute it with level 2 to catch any dynamic property usage.
phpstan analyze --level=2 .
With the latest example you can have:
- Access to an undefined property User::$age because of accessing age in the constructor;
- Access to an undefined property User::$nane because the typo (nane instead of name).
My considerations
This is a great feature with the goal to improve the quality and lower the hidden mistakes.
This feature, could have a great negative impact on the existing code. Are we sure about that ?
Some considerations:
- watching the roadmap of PHP 8 and the forecast, we can use PHP 8 for “legacy code” for years;
- if you are using a static code analysis, probably your code doesn’t use dynamic property;
- if you are not using static code, the first thing to do is launch phpstan with level 2.
So … welcome to “PHP RFC: Deprecate dynamic properties” and let’s prepare for the future ;)
Do you like or dislike “Deprecate dynamic properties”?