Skip to content

Commit 6513e68

Browse files
committed
Add support for final properties
1 parent 742bb33 commit 6513e68

30 files changed

+1059
-32
lines changed

Zend/tests/errmsg_038.phpt

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--TEST--
2+
Test that ArrayAccess works for final properties as expected
3+
--FILE--
4+
<?php
5+
6+
class Foo implements ArrayAccess
7+
{
8+
final private string $property1;
9+
final private string $property2 = "";
10+
11+
function offsetExists($offset)
12+
{
13+
return isset($this->$offset);
14+
}
15+
16+
function offsetGet($offset)
17+
{
18+
return $this->$offset ?? null;
19+
}
20+
21+
function offsetSet($offset, $value)
22+
{
23+
$this->$offset = $value;
24+
}
25+
26+
function offsetUnset($offset){
27+
unset($this->$offset);
28+
}
29+
}
30+
31+
$foo = new Foo();
32+
33+
$foo["property1"] = "foo";
34+
35+
try {
36+
$foo["property1"] = "foo";
37+
} catch (Error $exception) {
38+
echo $exception->getMessage() . "\n";
39+
}
40+
41+
try {
42+
$foo["property2"] = "foo";
43+
} catch (Error $exception) {
44+
echo $exception->getMessage() . "\n";
45+
}
46+
47+
$foo["property3"] = "foo";
48+
49+
?>
50+
--EXPECT--
51+
Cannot assign value to final property Foo::$property1 after initialization
52+
Cannot assign value to final property Foo::$property2 after initialization
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
--TEST--
2+
Test that final properties can't be incremented/decremented
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
final public int $property1;
9+
final public int $property2 = 2;
10+
11+
public function __construct()
12+
{
13+
$this->property1 = 1;
14+
$this->property3 = 3;
15+
}
16+
}
17+
18+
$foo = new Foo();
19+
20+
try {
21+
++$foo->property1;
22+
} catch (Error $exception) {
23+
echo $exception->getMessage() . "\n";
24+
}
25+
26+
try {
27+
++$foo->property2;
28+
} catch (Error $exception) {
29+
echo $exception->getMessage() . "\n";
30+
}
31+
32+
try {
33+
$foo->property1++;
34+
} catch (Error $exception) {
35+
echo $exception->getMessage() . "\n";
36+
}
37+
38+
try {
39+
$foo->property2++;
40+
} catch (Error $exception) {
41+
echo $exception->getMessage() . "\n";
42+
}
43+
44+
try {
45+
--$foo->property1;
46+
} catch (Error $exception) {
47+
echo $exception->getMessage() . "\n";
48+
}
49+
50+
try {
51+
--$foo->property2;
52+
} catch (Error $exception) {
53+
echo $exception->getMessage() . "\n";
54+
}
55+
56+
try {
57+
$foo->property1--;
58+
} catch (Error $exception) {
59+
echo $exception->getMessage() . "\n";
60+
}
61+
62+
try {
63+
$foo->property2--;
64+
} catch (Error $exception) {
65+
echo $exception->getMessage() . "\n";
66+
}
67+
68+
?>
69+
--EXPECT--
70+
Cannot modify final property Foo::$property1 after initialization
71+
Cannot modify final property Foo::$property2 after initialization
72+
Cannot modify final property Foo::$property1 after initialization
73+
Cannot modify final property Foo::$property2 after initialization
74+
Cannot modify final property Foo::$property1 after initialization
75+
Cannot modify final property Foo::$property2 after initialization
76+
Cannot modify final property Foo::$property1 after initialization
77+
Cannot modify final property Foo::$property2 after initialization
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
--TEST--
2+
Test that final properties can't be incremented/decremented by reference
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
final public int $property1;
9+
final public int $property2 = 2;
10+
11+
public function __construct()
12+
{
13+
$this->property1 = 1;
14+
}
15+
}
16+
17+
$foo = new Foo();
18+
foreach ($foo as &$property) {
19+
try {
20+
++$property;
21+
} catch (Error $exception) {
22+
echo $exception->getMessage() . "\n";
23+
}
24+
}
25+
26+
var_dump($foo);
27+
28+
$foo = new Foo();
29+
foreach ($foo as &$property) {
30+
try {
31+
$property++;
32+
} catch (Error $exception) {
33+
echo $exception->getMessage() . "\n";
34+
}
35+
}
36+
37+
var_dump($foo);
38+
39+
foreach ($foo as &$property) {
40+
try {
41+
--$property;
42+
} catch (Error $exception) {
43+
echo $exception->getMessage() . "\n";
44+
}
45+
}
46+
47+
var_dump($foo);
48+
49+
foreach ($foo as &$property) {
50+
try {
51+
$property--;
52+
} catch (Error $exception) {
53+
echo $exception->getMessage() . "\n";
54+
}
55+
}
56+
57+
var_dump($foo);
58+
59+
?>
60+
--EXPECTF--
61+
Cannot increment a reference held by final property Foo::$property1
62+
Cannot increment a reference held by final property Foo::$property2
63+
object(Foo)#1 (2) {
64+
["property1"]=>
65+
int(%d)
66+
["property2"]=>
67+
&int(%d)
68+
}
69+
Cannot increment a reference held by final property Foo::$property1
70+
Cannot increment a reference held by final property Foo::$property2
71+
object(Foo)#2 (2) {
72+
["property1"]=>
73+
int(%d)
74+
["property2"]=>
75+
&int(%d)
76+
}
77+
Cannot decrement a reference held by final property Foo::$property1
78+
Cannot decrement a reference held by final property Foo::$property2
79+
object(Foo)#2 (2) {
80+
["property1"]=>
81+
int(-%d)
82+
["property2"]=>
83+
&int(-%d)
84+
}
85+
Cannot decrement a reference held by final property Foo::$property1
86+
Cannot decrement a reference held by final property Foo::$property2
87+
object(Foo)#2 (2) {
88+
["property1"]=>
89+
int(-%d)
90+
["property2"]=>
91+
&int(-%d)
92+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
Test that the __get() magic method works when reading from a final property
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
final private array $properties = [
9+
"property1" => "foo",
10+
"property2" => null,
11+
];
12+
13+
public function __isset($name): bool
14+
{
15+
return isset($this->properties[$name]);
16+
}
17+
18+
public function __get($name)
19+
{
20+
return $this->properties[$name] ?? null;
21+
}
22+
}
23+
24+
$foo = new Foo();
25+
26+
var_dump(isset($foo->property1));
27+
var_dump($foo->property1);
28+
29+
var_dump(isset($foo->property2));
30+
var_dump($foo->property2);
31+
32+
var_dump(isset($foo->property3));
33+
var_dump($foo->property3);
34+
35+
?>
36+
--EXPECT--
37+
bool(true)
38+
string(3) "foo"
39+
bool(false)
40+
NULL
41+
bool(false)
42+
NULL
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
Test that the __set() magic method works as expected when a final property is modified
3+
--XFAIL--
4+
The array can be still modified even though it's final
5+
--FILE--
6+
<?php
7+
8+
class Foo
9+
{
10+
final private array $properties = [
11+
"property1" => "foo",
12+
"property2" => null,
13+
"property3" => [],
14+
];
15+
16+
public function __set($name, $value): void
17+
{
18+
$this->properties[$name] = $value;
19+
}
20+
}
21+
22+
$foo = new Foo();
23+
24+
try {
25+
$foo->property1 = "foo";
26+
} catch (Error $exception) {
27+
echo $exception->getMessage() . "\n";
28+
}
29+
30+
try {
31+
$foo->property2 = "foo";
32+
} catch (Error $exception) {
33+
echo $exception->getMessage() . "\n";
34+
}
35+
36+
try {
37+
$foo->property3[] = "foo";
38+
} catch (Error $exception) {
39+
echo $exception->getMessage() . "\n";
40+
}
41+
42+
try {
43+
$foo->property4 = "foo";
44+
} catch (Error $exception) {
45+
echo $exception->getMessage() . "\n";
46+
}
47+
48+
?>
49+
--EXPECT--
50+
Cannot modify final property Foo::$properties after initialization
51+
Cannot modify final property Foo::$properties after initialization
52+
Cannot modify final property Foo::$properties after initialization
53+
Cannot modify final property Foo::$properties after initialization
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
Test that the __set() magic method works as expected for final properties
3+
--FILE--
4+
<?php
5+
6+
class Foo
7+
{
8+
final private string $property1 = "";
9+
final private string $property2;
10+
11+
public function __set($name, $value): void
12+
{
13+
$this->$name = $value;
14+
}
15+
}
16+
17+
$foo = new Foo();
18+
19+
try {
20+
$foo->property1 = "foo";
21+
} catch (Error $exception) {
22+
echo $exception->getMessage() . "\n";
23+
}
24+
25+
$foo->property2 = "foo";
26+
27+
try {
28+
$foo->property2 = "foo";
29+
} catch (Error $exception) {
30+
echo $exception->getMessage() . "\n";
31+
}
32+
33+
34+
?>
35+
--EXPECT--
36+
Cannot assign value to final property Foo::$property1 after initialization
37+
Cannot assign value to final property Foo::$property2 after initialization

0 commit comments

Comments
 (0)