phptools-docs
phptools-docs copied to clipboard
Undefined property on class with `#[\AllowDynamicProperties]` attribute
Code:
namespace Test {
#[\AllowDynamicProperties]
final class DynamicTemplate
{
}
$template = new DynamicTemplate();
echo $template->bar; # Undefined property: DynamicTemplate::$bar PHP0416
final class MagicTemplate
{
public function __get(string $name): mixed
{
return null;
}
}
$template = new MagicTemplate();
echo $template->bar; # OK – no error
}
There shoulde be no error when class is marked with #[\AllowDynamicProperties] for back compatibility with php 8.2 deprecated dynamic properties unless this attribute is present
We do check unknown properties for any class; the attribute AllowDynamicProperties does not have the same meaning as the use of __get function.
In this sample above, the error PHP0416 is correct since the class does not have that property and the code will fail in run-time.
In this sample above, the error PHP0416 is correct since the class does not have that property and the code will fail in run-time.
It will fail, because i oversimplified the code – the property was not set before. Here is the code when both cases are working same – but one is reporting problem – but no error is thrown runtime – dynamic properties are allowed in PHP – deprecated with ability to still them with AllowDynamicProperties attribute
namespace Test {
#[\AllowDynamicProperties]
final class DynamicTemplate
{
}
$template = new DynamicTemplate();
$template->bar = 'foo';
echo $template->bar; # Undefined property: DynamicTemplate::$bar PHP0416
final class MagicTemplate
{
public function __get(string $name): mixed
{
return $this->{$name};
}
}
$template = new MagicTemplate();
$template->bar = 'foo';
echo $template->bar; # OK – no error
}
I think classes with __get/__set/__issets could be treated same as with #[\AllowDynamicProperties] attribute.
Basically the attributed class:
#[\AllowDynamicProperties]
final class DynamicTemplate
{
}
behaves same as class with magic methods:
final class DynamicTemplate
{
public function __get(string $name): mixed
{
return $this->{$name};
}
public function __set(string $name, mixed $value): mixed
{
return $this->{$name} = $value;
}
public function __isset(string $name): mixed
{
return \property_exists($this, $name);
}
}
It is implemeneted like this (using attribute) in Nette framework template objects: https://github.com/nette/application/blob/master/src/Bridges/ApplicationLatte/DefaultTemplate.php
Just by adding simple __get implementation into DefaultTemplate all reported problems are resolved – but there is no need for it to be there – as it is the default php behaviour.
public function __get(string $name): mixed {
return $this->{$name};
}
AllowDynamicProperties is something different.
~~The warning about an unknown property has nothing to do with the class dynamicity; we simply warn about a property whose use will cause a runtime error.~~
The diagnostic PHP0416 marks property access which may cause a run-time error - i.e. is not defined dynamically or statically.