Skip to content

Property hooks cause an infinite recursion in traits #15240

@dlsrc

Description

@dlsrc

Description

If I put the hook code in a class, everything works as expected:

<?php

class TestClass {
    public int $foo {
        set(int $foo) {
            if ($foo > 10) {
                $this->foo = 10;
            }
            elseif ($foo < 1) {
                $this->foo = 1;
            }
            else {
                $this->foo = $foo;
            }
        }
    }

    public function __construct() {
        $this->foo = 1;
    }

    public function __toString() {
        return (string) $this->foo;
    }
}

$test = new TestClass;
$test->foo = 400;
print $test;

Result is:

10

Ok.
But if I need to use a trait:

<?php

trait TestTrait {
    public int $foo {
        set(int $foo) {
            if ($foo > 10) {
                $this->foo = 10;
            }
            elseif ($foo < 1) {
                $this->foo = 1;
            }
            else {
                $this->foo = $foo;
            }
        }
    }
}

class TestClass {
    use TestTrait;

    public function __construct() {
        $this->foo = 1;
    }

    public function __toString() {
        return (string) $this->foo;
    }
}

$test = new TestClass;
$test->foo = 400;
print $test;

Resulted in this output:

PHP Fatal error:  Uncaught Error: Maximum call stack size of 8339456 bytes (zend.max_allowed_stack_size - zend.reserved_stack_size) reached. Infinite recursion? in /var/www/hosts/pub/tests/test.php:5
#0 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#1 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#2 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#3 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#4 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#5 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
.
.
.
#9815 /var/www/hosts/pub/tests/test.php(13): TestClass->$foo::set()
#9816 /var/www/hosts/pub/tests/test.php(37): TestClass->$foo::set()
#9817 /var/www/hosts/pub/tests/test.php(45): TestClass->__construct()
#9818 {main}
  thrown in /var/www/hosts/pub/tests/test.php on line 5

But I expected this output instead:

10

PHP Version

PHP 8.4.0alpha4

Operating System

RHEL9 and Windows10

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions