php内置函数分析之array_column()
1 PHP_FUNCTION(array_column) 2 { 3 zval *zcolumn = NULL, *zkey = NULL, *data; 4 HashTable *arr_hash; 5 zval *zcolval = NULL, *zkeyval = NULL, rvc, rvk; 6 7 // !如果接收了一个php语言里的null变量,则直接将其转成C语言里的NULL,而不是封装成IS_NULL类型的zval 8 if (zend_parse_parameters(ZEND_NUM_ARGS(), "hz!|z!", &arr_hash, &zcolumn, &zkey) == FAILURE) { 9 return; 10 } 11 12 /* 检查colunm和index是否有效(只能为数字和对象,对象需能转换为字符串)。 13 * 无效则报The %s key should be either a string or an integer的warning错误。 14 */ 15 if ((zcolumn && !array_column_param_helper(zcolumn, "column")) || 16 (zkey && !array_column_param_helper(zkey, "index"))) { 17 RETURN_FALSE; 18 } 19 // 初始化返回值 20 array_init(return_value); 21 // 循环遍历数组 22 ZEND_HASH_FOREACH_VAL(arr_hash, data) { 23 ZVAL_DEREF(data); 24 25 if (!zcolumn) { // column未设置 26 zcolval = data; 27 } else if ((zcolval = array_column_fetch_prop(data, zcolumn, &rvc)) == NULL) {// 该列的值为NULL,则跳过,进入下一循环 28 continue; 29 } 30 31 /* Failure will leave zkeyval alone which will land us on the final else block below 32 * which is to append the value as next_index 33 */ 34 if (zkey) { 35 zkeyval = array_column_fetch_prop(data, zkey, &rvk); // 获取zkey对应的列,作为返回数组的键/索引 36 } 37 38 Z_TRY_ADDREF_P(zcolval); 39 // 返回值数组:array(zkeyval=>zcolval,...) 40 if (zkeyval && Z_TYPE_P(zkeyval) == IS_STRING) { 41 zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR_P(zkeyval), zcolval); 42 } else if (zkeyval && Z_TYPE_P(zkeyval) == IS_LONG) { 43 add_index_zval(return_value, Z_LVAL_P(zkeyval), zcolval); 44 } else if (zkeyval && Z_TYPE_P(zkeyval) == IS_OBJECT) { 45 zend_string *key = zval_get_string(zkeyval); 46 zend_symtable_update(Z_ARRVAL_P(return_value), key, zcolval); 47 zend_string_release(key); 48 } else { 49 // 没有zkeyval,则返回值数组为索引数组 50 add_next_index_zval(return_value, zcolval); 51 } 52 /* 清理内存 */ 53 if (zcolval == &rvc) { 54 zval_ptr_dtor(&rvc); 55 } 56 if (zkeyval == &rvk) { 57 zval_ptr_dtor(&rvk); 58 } 59 } ZEND_HASH_FOREACH_END(); 60 }