Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PHP 8.1: Unable to load classes with public readonly properties #27

Closed
AnnaDamm opened this issue Dec 8, 2022 · 0 comments
Closed

PHP 8.1: Unable to load classes with public readonly properties #27

AnnaDamm opened this issue Dec 8, 2022 · 0 comments

Comments

@AnnaDamm
Copy link
Contributor

AnnaDamm commented Dec 8, 2022

When loading a class with readonly properties, an error is thrown: PHP Fatal error: Uncaught Error: Cannot initialize readonly property ...

This happens, because readonly properties

TestCase:

<?php

require 'vendor/autoload.php';

use Brick\VarExporter\VarExporter;

class Test
{
    public function __construct(
        public readonly string $foo
    ) {
    }
}

$object = new Test('bar');
$string = VarExporter::export($object, VarExporter::ADD_RETURN);
echo $string;

$newObject = eval($string);
echo "yay!";

Output

return (static function() {
    $class = new \ReflectionClass(\Test::class);
    $object = $class->newInstanceWithoutConstructor();

    $object->foo = 'bar';

    return $object;
})();

Fatal error: Uncaught Error: Cannot initialize readonly property Test::$foo from global scope in  test.php(19) : eval()'d code on line 5

Error: Cannot initialize readonly property Test::$foo from global scope in test.php(19) : eval()'d code on line 5

Expected Output

return (static function() {
    $class = new \ReflectionClass(\Test::class);
    $object = $class->newInstanceWithoutConstructor();
    (function() {
        $this->foo = 'bar';
    })->bindTo($object, \Test::class)();

    return $object;
})();yay!

Possible solution

instead of just setting the property on the object via $object->foo = 'bar' it should be set via bindTo:

(function() {
        $this->foo = 'bar';
    })->bindTo($object, \Test::class)();

one could use $property-> isReadOnly to determine if this is necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant