Skip to content

Commit 6840873

Browse files
committed
feat: allow hooks for backed readonly properties
1 parent 690cde6 commit 6840873

19 files changed

+529
-33
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ PHP NEWS
5353
evaluation) and GH-18464 (Recursion protection for deprecation constants not
5454
released on bailout). (DanielEScherzer and ilutov)
5555
. Fixed AST printing for immediately invoked Closure. (Dmitrii Derepko)
56+
. Property hooks are now allowed on backed readonly properties. ()
5657

5758
- Curl:
5859
. Added curl_multi_get_handles(). (timwolla)

UPGRADING

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ PHP 8.5 UPGRADE NOTES
144144
RFC: https://wiki.php.net/rfc/attributes-on-constants
145145
. The #[\Deprecated] attribute can now be used on constants.
146146
RFC: https://wiki.php.net/rfc/attributes-on-constants
147+
. Property hooks are now allowed on backed readonly properties.
148+
RFC: https://wiki.php.net/rfc/readonly_hooks
147149

148150
- Curl:
149151
. Added support for share handles that are persisted across multiple PHP

Zend/tests/property_hooks/gh15419_1.phpt

Lines changed: 0 additions & 12 deletions
This file was deleted.

Zend/tests/property_hooks/gh15419_2.phpt

Lines changed: 0 additions & 14 deletions
This file was deleted.
Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,73 @@
11
--TEST--
2-
Hooked properties cannot be readonly
2+
Backed readonly property may have nice hooks
33
--FILE--
44
<?php
55

6-
class Test {
7-
public readonly int $prop { get; set; }
6+
// class readonly
7+
final readonly class Foo
8+
{
9+
public function __construct(
10+
public array $values {
11+
set(array $value) => array_map(strtoupper(...), $value);
12+
},
13+
) {}
814
}
915

16+
// property readonly
17+
final class Foo2
18+
{
19+
public function __construct(
20+
public readonly array $values {
21+
set(array $value) => array_map(strtoupper(...), $value);
22+
},
23+
) {}
24+
}
25+
26+
// redundant readonly
27+
final readonly class Foo3
28+
{
29+
public function __construct(
30+
public readonly array $values {
31+
set(array $value) => array_map(strtoupper(...), $value);
32+
get => $this->makeNicer($this->values);
33+
},
34+
) {}
35+
36+
public function makeNicer(array $entries): array
37+
{
38+
return array_map(
39+
fn($i, $entry) => $entry . strtoupper(['', 'r', 'st'][$i]), array_keys($entries),
40+
$entries
41+
);
42+
}
43+
}
44+
45+
\var_dump(new Foo(['yo,', 'you', 'can'])->values);
46+
\var_dump(new Foo2(['just', 'do', 'things'])->values);
47+
\var_dump(new Foo3(['nice', 'nice', 'nice'])->values);
1048
?>
11-
--EXPECTF--
12-
Fatal error: Hooked properties cannot be readonly in %s on line %d
49+
--EXPECT--
50+
array(3) {
51+
[0]=>
52+
string(3) "YO,"
53+
[1]=>
54+
string(3) "YOU"
55+
[2]=>
56+
string(3) "CAN"
57+
}
58+
array(3) {
59+
[0]=>
60+
string(4) "JUST"
61+
[1]=>
62+
string(2) "DO"
63+
[2]=>
64+
string(6) "THINGS"
65+
}
66+
array(3) {
67+
[0]=>
68+
string(4) "NICE"
69+
[1]=>
70+
string(5) "NICER"
71+
[2]=>
72+
string(6) "NICEST"
73+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
Backed property, readonly class
3+
--FILE--
4+
<?php
5+
6+
// readonly class
7+
readonly class Test {
8+
public int $prop {
9+
get => $this->prop;
10+
set => $value;
11+
}
12+
13+
public function __construct(int $v) {
14+
$this->prop = $v;
15+
}
16+
17+
public function set($v)
18+
{
19+
$this->prop = $v;
20+
}
21+
}
22+
23+
$t = new Test(42);
24+
var_dump($t->prop);
25+
try {
26+
$t->set(43);
27+
} catch (Error $e) {
28+
echo $e->getMessage(), "\n";
29+
}
30+
try {
31+
$t->prop = 43;
32+
} catch (Error $e) {
33+
echo $e->getMessage(), "\n";
34+
}
35+
var_dump($t->prop);
36+
?>
37+
--EXPECT--
38+
int(42)
39+
Cannot modify readonly property Test::$prop
40+
Cannot modify protected(set) readonly property Test::$prop from global scope
41+
int(42)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Backed property cannot redeclare readonly as non-readonly property
3+
--FILE--
4+
<?php
5+
6+
readonly class ParentClass {
7+
public int $prop;
8+
}
9+
10+
class Test extends ParentClass {
11+
public function __construct(
12+
public int $prop {
13+
get => $this->prop;
14+
set => $value;
15+
}
16+
) {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Non-readonly class Test cannot extend readonly class ParentClass in %s on line %d
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Backed property cannot redeclare non-readonly as readonly property
3+
--FILE--
4+
<?php
5+
6+
class ParentClass {
7+
public int $prop;
8+
}
9+
10+
readonly class Test extends ParentClass {
11+
public function __construct(
12+
public int $prop {
13+
get => $this->prop;
14+
set => $value;
15+
}
16+
) {}
17+
}
18+
19+
?>
20+
--EXPECTF--
21+
Fatal error: Readonly class Test cannot extend non-readonly class ParentClass in %s on line %d
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
Backed property, promoted, readonly class
3+
--FILE--
4+
<?php
5+
6+
// readonly class, promoted
7+
readonly class Test {
8+
public function __construct(
9+
public int $prop {
10+
get => $this->prop;
11+
set => $value;
12+
}
13+
) {}
14+
15+
public function set($v)
16+
{
17+
$this->prop = $v;
18+
}
19+
}
20+
21+
$t = new Test(42);
22+
var_dump($t->prop);
23+
try {
24+
$t->set(43);
25+
} catch (Error $e) {
26+
echo $e->getMessage(), "\n";
27+
}
28+
try {
29+
$t->prop = 43;
30+
} catch (Error $e) {
31+
echo $e->getMessage(), "\n";
32+
}
33+
var_dump($t->prop);
34+
?>
35+
--EXPECT--
36+
int(42)
37+
Cannot modify readonly property Test::$prop
38+
Cannot modify protected(set) readonly property Test::$prop from global scope
39+
int(42)
40+
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Virtual promoted property in readonly class cannot have hooks
3+
--FILE--
4+
<?php
5+
6+
readonly class Test {
7+
public function __construct(
8+
public int $prop {
9+
get => 42;
10+
}
11+
) {}
12+
}
13+
14+
?>
15+
--EXPECTF--
16+
Fatal error: Hooked virtual properties cannot be readonly in %s on line %d

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy