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 }