当前位置: 首页 > 后端技术 > PHP

每天一个php函数——array_change_key_case

时间:2023-03-29 23:21:55 PHP

因为已经有文档了,可能有人会觉得我这样写有点多余。但并不是每个PHPer都会仔细阅读文档,自然也有一些功能可能没有听说过(很遗憾,我也是其中之一)。也希望通过写这些文章,能够促使我完整的阅读文档,同时也能给其他PHPer一个参考,“啊,原来有这个功能”。同时,我也希望通过写这些文章,能够读懂各个功能的C语言实现。也实现了自我驱动学习。函数原型array_change_key_case(array$array[,int$case=CASE_LOWER])该函数的具体作用是将数组中的所有英文字母转为大写或小写。我们可以看到这个函数接收两个参数并返回一个数组。第一个参数数组没有使用引用方式,也就是说函数不会改变原来的数组,会生成一个新的数组作为返回值。第二个参数是可选的,它控制函数是转换为大写还是小写。默认是转换为小写。函数使用第二个参数函数的第二个参数传入一个预定义的常量,即CASE_LOWER和CASE_UPPER,前者是将key转为小写,后者也是函数的默认值;后者是将密钥转换为大写。使用$arr=['lower'=>1,];$toLower=array_change_key_case($arr,CASE_LOWER);//我想,不管它的默认值是多少,我们都应该写这第二个参数。我们的代码是写给人们阅读的,而不是给机器看的。//所以我们的代码应该包含尽可能多的语义。$toUpper=array_change_key_case($arr,CASE_UPPER);var_dump($toLower);/**['lower'=>1]*/var_dump($toUpper);/**['LOWER'=>1]*/但是,这个函数不是递归的。让我们看看下面的例子。$arr=['较低'=>['较低'=>1,],];$toLower=array_change_key_case($arr,CASE_LOWER);var_dump($toLower);/**['lower'=>['Lower'=>1,],]*/使用这个函数有一个陷阱。陷阱是转换后,如果结果中有两个相同的键,最后一个将被保留。例如。$arr=['key'=>1,'kEy'=>2,'key'=>3,];$toLower=array_change_key_case($arr,CASE_UPPER);var_dump($toLower);//['key'=>3]在这个例子中,我们发现当进行转换时,三个键变得相同,那么在这种情况下,只有最后一个元素会被保留为键。这里的结果数组是['key'=>3]。实现该功能的内核源码在php-src/ext/standard/array.c。源码我们先来看一下源码。PHP_FUNCTION(array_change_key_case){zval*array,*entry;zend_string*string_key;zend_string*new_key;zend_ulongnum_key;zend_longchange_to_upper=0;ZEND_PARSE_PARAMETERS_START(1,2)Z_PARAM_ARRAY(数组)Z_PARAM_OPTIONALZ_PARAM_LONG(change_to_upper)ZEND_PARSE_PARAMETERS_END();array_init_size(return_value,zend_hash_num_elements(Z_ARRVAL_P(array)));ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(array),num_key,string_key,entry){if(!string_key){entry=zend_hash_index_update(Z_ARRVAL_P(return_value),num_key,entry);}}else{if(change_to_upper){new_key=php_string_toupper(string_key);}else{new_key=php_string_tolower(string_key);}entry=zend_hash_update(Z_ARRVAL_P(return_value),new_key,entry);zend_string_release(new_key);}zval_add_ref(条目);}ZEND_HASH_FOREACH_END();}关于PHP_FUNCTION宏熟悉PHP扩展开发的同学应该都知道,PHP_FUNCTION宏是用来定义一个PHP函数的,参数是PHP函数的函数名。关于这个宏,有兴趣的可以去看源码。它其实是将PHP_FUNCTION(array_change_key_case)替换成了voidzif_array_change_key_case(zend_execute_data*execute_data,zval*return_value)这样的函数定义。注意里面的return_value变量,后面会用到。逻辑代码其实真正的逻辑代码是在ZEND_HASH_FOREACH_KEY_VAL宏和ZEND_HASH_FOREACH_END之间。上面的宏用于检查和获取传递给PHP函数的变量。我们可以看到zend_longchange_to_upper=0;这个用来判断是大写还是小写。此处定义的默认值为0,因此此函数的默认值为小写。整个函数的核心代码就是php_string_toupper和php_string_tolower这两个函数。这是其中一个的代码。PHPAPIzend_string*php_string_toupper(zend_string*s){unsignedchar*c,*e;c=(unsignedchar*)ZSTR_VAL(s);e=c+ZSTR_LEN(s);while(c