Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ PHP NEWS
evaluation) and GH-18464 (Recursion protection for deprecation constants not
released on bailout). (DanielEScherzer and ilutov)
. Fixed AST printing for immediately invoked Closure. (Dmitrii Derepko)
. Property hooks are now allowed on backed readonly properties. (Crell, NickSdot and iluuu1994)

- Curl:
. Added curl_multi_get_handles(). (timwolla)
Expand Down
2 changes: 2 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ PHP 8.5 UPGRADE NOTES
RFC: https://wiki.php.net/rfc/attributes-on-constants
. The #[\Deprecated] attribute can now be used on constants.
RFC: https://wiki.php.net/rfc/attributes-on-constants
. Property hooks are now allowed on backed readonly properties.
RFC: https://wiki.php.net/rfc/readonly_hooks

- Curl:
. Added support for share handles that are persisted across multiple PHP
Expand Down
12 changes: 0 additions & 12 deletions Zend/tests/property_hooks/gh15419_1.phpt

This file was deleted.

14 changes: 0 additions & 14 deletions Zend/tests/property_hooks/gh15419_2.phpt

This file was deleted.

12 changes: 0 additions & 12 deletions Zend/tests/property_hooks/readonly.phpt

This file was deleted.

41 changes: 41 additions & 0 deletions Zend/tests/property_hooks/readonly_class_property_backed.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
--TEST--
Backed property in readonly class may have hooks
--FILE--
<?php

// readonly class
readonly class Test {
public int $prop {
get => $this->prop;
set => $value;
}

public function __construct(int $v) {
$this->prop = $v;
}

public function set($v)
{
$this->prop = $v;
}
}

$t = new Test(42);
var_dump($t->prop);
try {
$t->set(43);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
$t->prop = 43;
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($t->prop);
?>
--EXPECT--
int(42)
Cannot modify readonly property Test::$prop
Cannot modify protected(set) readonly property Test::$prop from global scope
int(42)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
Non-readonly class cannot extend readonly class
--FILE--
<?php

readonly class ParentClass {
public int $prop;
}

class Test extends ParentClass {
public function __construct(
public int $prop {
get => $this->prop;
set => $value;
}
) {}
}

?>
--EXPECTF--
Fatal error: Non-readonly class Test cannot extend readonly class ParentClass in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
Readonly class cannot extend non-readonly class
--FILE--
<?php

class ParentClass {
public int $prop;
}

readonly class Test extends ParentClass {
public function __construct(
public int $prop {
get => $this->prop;
set => $value;
}
) {}
}

?>
--EXPECTF--
Fatal error: Readonly class Test cannot extend non-readonly class ParentClass in %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
--TEST--
Backed promoted property in readonly class may have hooks
--FILE--
<?php

// readonly class, promoted
readonly class Test {
public function __construct(
public int $prop {
get => $this->prop;
set => $value;
}
) {}

public function set($v)
{
$this->prop = $v;
}
}

$t = new Test(42);
var_dump($t->prop);
try {
$t->set(43);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
$t->prop = 43;
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($t->prop);
?>
--EXPECT--
int(42)
Cannot modify readonly property Test::$prop
Cannot modify protected(set) readonly property Test::$prop from global scope
int(42)

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
Virtual promoted property in readonly class cannot have hooks
--FILE--
<?php

readonly class Test {
public function __construct(
public int $prop {
get => 42;
}
) {}
}

?>
--EXPECTF--
Fatal error: Hooked virtual properties cannot be readonly in %s on line %d
108 changes: 108 additions & 0 deletions Zend/tests/property_hooks/readonly_property_backed.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
--TEST--
Backed readonly property may have hooks
--FILE--
<?php

// readonly property
class Test {
public readonly int $prop {
get => $this->prop;
set => $value;
}

public function __construct(int $v) {
$this->prop = $v;
}

public function set($v)
{
$this->prop = $v;
}
}

$t = new Test(42);
var_dump($t->prop);
try {
$t->set(43);
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
try {
$t->prop = 43;
} catch (Error $e) {
echo $e->getMessage(), "\n";
}
var_dump($t->prop);

// class readonly
final readonly class Foo
{
public function __construct(
public array $values {
set(array $value) => array_map(strtoupper(...), $value);
},
) {}
}

// property readonly
final class Foo2
{
public function __construct(
public readonly array $values {
set(array $value) => array_map(strtoupper(...), $value);
},
) {}
}

// redundant readonly
final readonly class Foo3
{
public function __construct(
public readonly array $values {
set(array $value) => array_map(strtoupper(...), $value);
get => $this->makeNicer($this->values);
},
) {}

public function makeNicer(array $entries): array
{
return array_map(
fn($i, $entry) => $entry . strtoupper(['', 'r', 'st'][$i]), array_keys($entries),
$entries
);
}
}

\var_dump(new Foo(['yo,', 'you', 'can'])->values);
\var_dump(new Foo2(['just', 'do', 'things'])->values);
\var_dump(new Foo3(['nice', 'nice', 'nice'])->values);
?>
--EXPECT--
int(42)
Cannot modify readonly property Test::$prop
Cannot modify protected(set) readonly property Test::$prop from global scope
int(42)
array(3) {
[0]=>
string(3) "YO,"
[1]=>
string(3) "YOU"
[2]=>
string(3) "CAN"
}
array(3) {
[0]=>
string(4) "JUST"
[1]=>
string(2) "DO"
[2]=>
string(6) "THINGS"
}
array(3) {
[0]=>
string(4) "NICE"
[1]=>
string(5) "NICER"
[2]=>
string(6) "NICEST"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
Backed property cannot redeclare readonly as non-readonly property
--FILE--
<?php

class ParentClass {
public readonly int $prop;
}

class Test extends ParentClass {
public function __construct(
public int $prop {
get => $this->prop;
set => $value;
}
) {}
}

?>
--EXPECTF--
Fatal error: Cannot redeclare readonly property ParentClass::$prop as non-readonly Test::$prop %s on line %d
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
Backed property cannot redeclare non-readonly as readonly property
--FILE--
<?php

class ParentClass {
public int $prop;
}

class Test extends ParentClass {
public function __construct(
public readonly int $prop {
get => $this->prop;
set => $value;
}
) {}
}

?>
--EXPECTF--
Fatal error: Cannot redeclare non-readonly property ParentClass::$prop as readonly Test::$prop in %s on line %d
Loading