You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Using null as an array offset is not deprecated #20194
Deprecated: Using null as an array offset is deprecated, use an empty string instead in /var/www/test.php on line 5
1
But I expected this output instead:
Deprecated: Using null as an array offset is deprecated, use an empty string instead in /var/www/test.php on line 3
Deprecated: Using null as an array offset is deprecated, use an empty string instead in /var/www/test.php on line 5
1
PHP Version
PHP 8.5.0RC2 (cli) (built: Oct 9 2025 23:32:25) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.5.0RC2, Copyright (c) Zend Technologies
with Zend OPcache v8.5.0RC2, Copyright (c), by Zend Technologies
Probably this, but I again don't like how deprecations in the core propagate through everything and make things more complicated than they should be.
Not sure yet if the changes in zend_try_ct_eval_array are necessary, i.e. if we're allowed to emit a deprecation even for non-executed code?
diff --git a/Zend/Optimizer/sccp.c b/Zend/Optimizer/sccp.c
index bbf52d8cf69..38a28dcd488 100644
--- a/Zend/Optimizer/sccp.c+++ b/Zend/Optimizer/sccp.c@@ -1106,6 +1106,11 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o
if (op2) {
SKIP_IF_TOP(op2);
+ if (Z_TYPE_P(op2) == IS_NULL) {+ /* Emits deprecation at run-time. */+ SET_RESULT_BOT(result);+ return;+ }
}
/* We want to avoid keeping around intermediate arrays for each SSA variable in the
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 1b97974686e..4065e7a8618 100644
--- a/Zend/zend_API.c+++ b/Zend/zend_API.c@@ -2256,6 +2256,7 @@ ZEND_API zend_result array_set_zval_key(HashTable *ht, zval *key, zval *value) /
result = zend_symtable_update(ht, Z_STR_P(key), value);
break;
case IS_NULL:
+ zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");
result = zend_hash_update(ht, ZSTR_EMPTY_ALLOC(), value);
break;
case IS_RESOURCE:
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index b51a519533c..e31bc28affa 100644
--- a/Zend/zend_compile.c+++ b/Zend/zend_compile.c@@ -10259,13 +10259,14 @@ static bool zend_try_ct_eval_array(zval *result, zend_ast *ast) /* {{{ */
zend_hash_index_update(Z_ARRVAL_P(result), 1, value);
break;
case IS_NULL:
- zend_hash_update(Z_ARRVAL_P(result), ZSTR_EMPTY_ALLOC(), value);- break;+ /* Null key will generate a warning at run-time. */+ goto fail;
default:
zend_error_noreturn(E_COMPILE_ERROR, "Illegal offset type");
break;
}
} else if (!zend_hash_next_index_insert(Z_ARRVAL_P(result), value)) {
+fail:
zval_ptr_dtor_nogc(value);
zval_ptr_dtor(result);
return 0;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 3c3065e1568..4e4a7cfdf78 100644
--- a/Zend/zend_vm_def.h+++ b/Zend/zend_vm_def.h@@ -6278,7 +6278,11 @@ ZEND_VM_C_LABEL(num_index):
} else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
offset = Z_REFVAL_P(offset);
ZEND_VM_C_GOTO(add_again);
- } else if (Z_TYPE_P(offset) == IS_NULL) {+ } else if (UNEXPECTED(Z_TYPE_P(offset) == IS_NULL)) {+ zend_error(E_DEPRECATED, "Using null as an array offset is deprecated, use an empty string instead");+ if (UNEXPECTED(EG(exception))) {+ HANDLE_EXCEPTION();+ }
str = ZSTR_EMPTY_ALLOC();
ZEND_VM_C_GOTO(str_index);
} else if (Z_TYPE_P(offset) == IS_DOUBLE) {
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 50870ce463d..fc8735de516 100644
Binary files a/Zend/zend_vm_execute.h and b/Zend/zend_vm_execute.h differ
You should handle $a[null] the same way you would handle $a['key_that_doesnt_exist']. Otherwise, 1000s of people each have to go and update dozens of lines of code to be like this:
It seems so unnecessary when it can be handled directly in the source code intuitively.
Further, the "use an empty string instead" part of the error message is misleading in the case of trying to access $a[null]. The error is suggesting they try accessing $a[''] which could also not exist or provide an incorrect value in that context.
$array[$nonNullKeyThatDoesntExist] and $array[$nullKeyThatDoesntExist] behave the same; this is intuitive
$array[$nonNullKeyThatExists] functions as usual
$array[$nullKeyThatExists] functions as usual; only show deprecation for $array[null => 'value'] and in a future version of PHP throw an error for $array[null => 'value']; when the developer is forced to remove their null key, point 1 handles $array[$nullKeyThatDoesntExist]
Activity
ndossche commentedon Oct 18, 2025
Probably this, but I again don't like how deprecations in the core propagate through everything and make things more complicated than they should be.
Not sure yet if the changes in zend_try_ct_eval_array are necessary, i.e. if we're allowed to emit a deprecation even for non-executed code?
Merge branch 'PHP-8.5'
thomas-0816 commentedon Oct 29, 2025
Thank You!
justin-oh commentedon Sep 22, 2026
I can get why
$array[null => 'value'];can be deprecated but why$a[null]?PHP is full of code like this:
You should handle
$a[null]the same way you would handle$a['key_that_doesnt_exist']. Otherwise, 1000s of people each have to go and update dozens of lines of code to be like this:It seems so unnecessary when it can be handled directly in the source code intuitively.
Further, the "use an empty string instead" part of the error message is misleading in the case of trying to access
$a[null]. The error is suggesting they try accessing$a['']which could also not exist or provide an incorrect value in that context.justin-oh commentedon Sep 22, 2026
Basically I would expect these scenarios:
$array[$nonNullKeyThatDoesntExist]and$array[$nullKeyThatDoesntExist]behave the same; this is intuitive$array[$nonNullKeyThatExists]functions as usual$array[$nullKeyThatExists]functions as usual; only show deprecation for$array[null => 'value']and in a future version of PHP throw an error for$array[null => 'value']; when the developer is forced to remove theirnullkey, point 1 handles$array[$nullKeyThatDoesntExist]