SoFunction
Updated on 2025-03-03

Necessity to parse non-numeric key names in arrays

I have seen many people who operate arrays without quotes for non-numeric key names in arrays
Copy the codeThe code is as follows:

  $array[key] = $value;

I can understand that some people may think that such code is "neat" and can be executed normally.
Even if he is "lucky" with a good configuration:
Copy the codeThe code is as follows:

error_reporting = ~E_NOTIC

He may always be immersed in his "neat" style, not seeing any NOTICE prompts, nor realizing how much performance he can lose if he does this~
Come on, let's take a look:
:
Copy the codeThe code is as follows:

<?php
   $array = array();
   $i = 0;
   while(++$i < 1000){
       $array['good'] = 2;
   }
?>

:
Copy the codeThe code is as follows:

<?php
   $array = array();
   $i = 0;
   while(++$i < 1000){
       $array[good] = 2;
   }
?>

Look at the running time (multiple average time):
Quoted marks:
Copy the codeThe code is as follows:

$ time php -f
real 0m0.013s
user 0m0.005s
sys 0m0.007

Unquoted:
Copy the codeThe code is as follows:

$ time php -f
PHP Notice: Use of undefined constant bad - assumed 'bad' in /home/huixinchen/tmp/
on line (NoTICE is omitted here)
real 0m0.100s
user 0m0.020s
sys 0m0.029

Look, how big is the difference?
Oh, maybe we should simulate the situation of those "lucky" people, remove the overhead spent on recording NOTICE, and see~
Copy the codeThe code is as follows:

$ time php -f
real 0m0.037s
user 0m0.018s
sys 0m0.018

We can see that basically, the efficiency loss of using quotes, and not using quotes is more than 3 times
So, where are these efficiency losses gone?
Let's take a look at the OPCODE sequence generated by the two files:
:
Copy the codeThe code is as follows:

filename: /home/huixinchen/tmp/
compiled vars: !0 = $array, !1 = $i
line # op fetch ext return operands
-------------------------------------------------------------------------------
   2 0 INIT_ARRAY ~0
         1 ASSIGN !0, ~0
   3 2 ASSIGN !1, 0
   4 3 PRE_INC $3 !1
         4 IS_SMALLER ~4 $3, 1000
         5 JMPZ ~4, ->9
   5 6 ZEND_ASSIGN_DIM !0, 'good'
         7 ZEND_OP_DATA 2, $6
   6 8 JMP ->3
   8 9 RETURN 1
        10* ZEND_HANDLE_EXCEPTIO

:
Copy the codeThe code is as follows:

filename: /home/huixinchen/tmp/
compiled vars: !0 = $array, !1 = $i
line # op fetch ext return operands
-------------------------------------------------------------------------------
   2 0 INIT_ARRAY ~0
         1 ASSIGN !0, ~0
   3 2 ASSIGN !1, 0
   4 3 PRE_INC $3 !1
         4 IS_SMALLER ~4 $3, 1000
         5 JMPZ ~4, ->10
   5 6 FETCH_CONSTANT ~5 'bad'
         7 ZEND_ASSIGN_DIM !0, ~5
         8 ZEND_OP_DATA 2, $7
   6 9 JMP ->3
   8 10 RETURN 1
        11* ZEND_HANDLE_EXCEPTIO

We can see (actually, according to NOTICE's prompt, we also know that it is known), PHP will take the key names without quotes as constants to obtain. When it cannot be found, throw a NOTICE, and then generate a string based on "constant" and then continue with this string as the key name~
You are smart and will definitely think that the following unpredictable errors may occur:
Copy the codeThe code is as follows:

define('key_name' , 'laruence');
....
//Omit a lot of lines of code
$array[key_name] = 2; //It becomes $array['laruence'] = 2;
//You will be very depressed with such a mistake, right?

Do you understand? The key names of non-numeric keys in the array must have quotes~
Oh, I remember someone would say that when string variables are replaced, writing quotes will cause errors,
Yes, standard writing:
Copy the codeThe code is as follows:

$string = "variable value is {$array['key']}"

I agree: "be lazy", but lazy should also have principles.
Finally, good code should not be disguised by closing error_reporting.
Note, the relevant logic of constants cannot be found in FETCH_CONSTANT OPCODE:
Copy the codeThe code is as follows:

....
if (!zend_get_constant(opline->,
     opline->, &EX_T(opline->).tmp_var TSRMLS_CC)) {
       zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
                opline->,
                opline->);
EX_T(opline->).tmp_var = opline->;//Get the "constant" name string
zval_copy_ctor(&EX_T(opline->).tmp_var);//Allocate space and generate strings
}
....