Skip to content

Commit 53aed48

Browse files
committed
Allow objects in define()
This was separately discussed in https://externals.io/message/114863, but also necessary for consistency now that https://wiki.php.net/rfc/new_in_initializers has landed. Closes GH-7149.
1 parent 59a5f89 commit 53aed48

File tree

6 files changed

+43
-84
lines changed

6 files changed

+43
-84
lines changed

UPGRADING

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ PHP 8.1 UPGRADE NOTES
195195
RFC: https://wiki.php.net/rfc/fibers
196196
. It is now possible to use "new ClassName()" expressions as parameter
197197
default values, static variable and global constant initializers, as well
198-
as attribute arguments.
198+
as attribute arguments. Objects can also be passed to `define()` now.
199199
RFC: https://wiki.php.net/rfc/new_in_initializers
200200
. Closures for callables can now be created using the syntax `myFunc(...)`,
201201
which is the same as `Closure::fromCallable('myFunc')`. Yes, the `...` is

Zend/tests/008.phpt

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,7 @@ var_dump(define("test const", 3));
1616
var_dump(define("test const", 3));
1717
var_dump(define("test", array(1)));
1818
var_dump(define("test1", fopen(__FILE__, 'r')));
19-
20-
try {
2119
var_dump(define("test2", new stdclass));
22-
} catch (TypeError $exception) {
23-
echo $exception->getMessage() . "\n";
24-
}
2520

2621
var_dump(constant(" "));
2722
var_dump(constant("[[["));
@@ -42,7 +37,7 @@ Warning: Constant test const already defined in %s on line %d
4237
bool(false)
4338
bool(true)
4439
bool(true)
45-
define(): Argument #2 ($value) cannot be an object, stdClass given
40+
bool(true)
4641
int(1)
4742
int(2)
4843
int(3)

Zend/tests/bug37811.phpt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@ class TestClass
1313

1414
define("Bar", new TestClass);
1515
var_dump(Bar);
16+
var_dump((string) Bar);
1617

18+
define("Baz", new stdClass);
19+
var_dump(Baz);
1720
try {
18-
define("Baz", new stdClass);
19-
} catch (TypeError $exception) {
20-
echo $exception->getMessage() . "\n";
21-
}
22-
23-
try {
24-
var_dump(Baz);
25-
} catch (Error $exception) {
26-
echo $exception->getMessage() . "\n";
21+
var_dump((string) Baz);
22+
} catch (Error $e) {
23+
echo $e->getMessage(), "\n";
2724
}
2825

2926
?>
3027
--EXPECT--
28+
object(TestClass)#1 (0) {
29+
}
3130
string(3) "Foo"
32-
define(): Argument #2 ($value) cannot be an object, stdClass given
33-
Undefined constant "Baz"
31+
object(stdClass)#2 (0) {
32+
}
33+
Object of class stdClass could not be converted to string

Zend/tests/constant_arrays.phpt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,9 @@ define('QUX', $y);
2323
$y[0] = 3;
2424
var_dump($x, $y, QUX);
2525

26-
// ensure objects not allowed in arrays
27-
try {
28-
define('ELEPHPANT', [new StdClass]);
29-
} catch (TypeError $exception) {
30-
echo $exception->getMessage() . "\n";
31-
}
26+
// objects are allowed in arrays
27+
define('ELEPHPANT', [new StdClass]);
28+
var_dump(ELEPHPANT);
3229

3330
// ensure recursion doesn't crash
3431
$recursive = [];
@@ -102,5 +99,9 @@ array(1) {
10299
[0]=>
103100
int(7)
104101
}
105-
define(): Argument #2 ($value) cannot be an object, stdClass given
102+
array(1) {
103+
[0]=>
104+
object(stdClass)#1 (0) {
105+
}
106+
}
106107
define(): Argument #2 ($value) cannot be a recursive array

Zend/tests/constants_002.phpt

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,14 @@ Defining constants with non-scalar values
33
--FILE--
44
<?php
55

6-
try {
7-
define('foo', new stdClass);
8-
} catch (TypeError $exception) {
9-
echo $exception->getMessage() . "\n";
10-
}
11-
12-
try {
13-
var_dump(foo);
14-
} catch (Error $e) {
15-
echo $e->getMessage(), "\n";
16-
}
17-
18-
define('foo', fopen(__FILE__, 'r'));
6+
define('foo', new stdClass);
197
var_dump(foo);
208

9+
define('bar', fopen(__FILE__, 'r'));
10+
var_dump(bar);
11+
2112
?>
22-
--EXPECT--
23-
define(): Argument #2 ($value) cannot be an object, stdClass given
24-
Undefined constant "foo"
25-
resource(5) of type (stream)
13+
--EXPECTF--
14+
object(stdClass)#1 (0) {
15+
}
16+
resource(%d) of type (stream)

Zend/zend_builtin_functions.c

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -420,20 +420,12 @@ static bool validate_constant_array_argument(HashTable *ht, int argument_number)
420420
GC_PROTECT_RECURSION(ht);
421421
ZEND_HASH_FOREACH_VAL(ht, val) {
422422
ZVAL_DEREF(val);
423-
if (Z_REFCOUNTED_P(val)) {
424-
if (Z_TYPE_P(val) == IS_ARRAY) {
425-
if (Z_REFCOUNTED_P(val)) {
426-
if (Z_IS_RECURSIVE_P(val)) {
427-
zend_argument_value_error(argument_number, "cannot be a recursive array");
428-
ret = 0;
429-
break;
430-
} else if (!validate_constant_array_argument(Z_ARRVAL_P(val), argument_number)) {
431-
ret = 0;
432-
break;
433-
}
434-
}
435-
} else if (Z_TYPE_P(val) != IS_STRING && Z_TYPE_P(val) != IS_RESOURCE) {
436-
zend_argument_type_error(argument_number, "cannot be an object, %s given", zend_zval_type_name(val));
423+
if (Z_TYPE_P(val) == IS_ARRAY && Z_REFCOUNTED_P(val)) {
424+
if (Z_IS_RECURSIVE_P(val)) {
425+
zend_argument_value_error(argument_number, "cannot be a recursive array");
426+
ret = 0;
427+
break;
428+
} else if (!validate_constant_array_argument(Z_ARRVAL_P(val), argument_number)) {
437429
ret = 0;
438430
break;
439431
}
@@ -496,35 +488,15 @@ ZEND_FUNCTION(define)
496488

497489
ZVAL_UNDEF(&val_free);
498490

499-
switch (Z_TYPE_P(val)) {
500-
case IS_LONG:
501-
case IS_DOUBLE:
502-
case IS_STRING:
503-
case IS_FALSE:
504-
case IS_TRUE:
505-
case IS_NULL:
506-
case IS_RESOURCE:
507-
break;
508-
case IS_ARRAY:
509-
if (Z_REFCOUNTED_P(val)) {
510-
if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) {
511-
RETURN_THROWS();
512-
} else {
513-
copy_constant_array(&c.value, val);
514-
goto register_constant;
515-
}
516-
}
517-
break;
518-
case IS_OBJECT:
519-
if (Z_OBJ_HT_P(val)->cast_object(Z_OBJ_P(val), &val_free, IS_STRING) == SUCCESS) {
520-
val = &val_free;
521-
break;
491+
if (Z_TYPE_P(val) == IS_ARRAY) {
492+
if (Z_REFCOUNTED_P(val)) {
493+
if (!validate_constant_array_argument(Z_ARRVAL_P(val), 2)) {
494+
RETURN_THROWS();
495+
} else {
496+
copy_constant_array(&c.value, val);
497+
goto register_constant;
522498
}
523-
ZEND_FALLTHROUGH;
524-
default:
525-
zval_ptr_dtor(&val_free);
526-
zend_argument_type_error(2, "cannot be an object, %s given", zend_zval_type_name(val));
527-
RETURN_THROWS();
499+
}
528500
}
529501

530502
ZVAL_COPY(&c.value, val);

0 commit comments

Comments
 (0)