Skip to content
On this page

compact 関数に関して

2021-04-15


compat 関数とは

compat 関数とは PHP の組み込み関数の1つで、変数をキーとバリューの関係にしてくれるという関数です。
使い方としては以下のような形になります。

$name  = "takurinton";
$age = 21;
$event = "me";

$me = array("name", "age");

$result = compact("me", $me);
echo $result;
1
2
3
4
5
6
7
8

このような形にすると出力は以下のようになります。

Array
(
    [me] => me
    [name] => takurinton
    [age] => 21
)
1
2
3
4
5
6

こんな感じで例えば今持ってる変数を連想配列にしてから JSON に変換してレスポンスを返したいなどという時に有効に利用できます。
今働いてるところでもこのような使用方法はよく見かけるため、便利だな〜とか思ってました。

コード見てみよう

実際にコードを見てみると この部分 で定義されているようです。

static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_value, zval *entry) /* {{{ */
{
	zval *value_ptr, data;

	ZVAL_DEREF(entry);
	if (Z_TYPE_P(entry) == IS_STRING) {
		if ((value_ptr = zend_hash_find_ind(eg_active_symbol_table, Z_STR_P(entry))) != NULL) {
			ZVAL_DEREF(value_ptr);
			Z_TRY_ADDREF_P(value_ptr);
			zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), value_ptr);
		} else if (zend_string_equals_literal(Z_STR_P(entry), "this")) {
			zend_object *object = zend_get_this_object(EG(current_execute_data));
			if (object) {
				ZVAL_OBJ_COPY(&data, object);
				zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
			}
		} else {
			php_error_docref(NULL, E_WARNING, "Undefined variable $%s", ZSTR_VAL(Z_STR_P(entry)));
		}
	} else if (Z_TYPE_P(entry) == IS_ARRAY) {
	    if (Z_REFCOUNTED_P(entry)) {
			if (Z_IS_RECURSIVE_P(entry)) {
				zend_throw_error(NULL, "Recursion detected");
				return;
			}
			Z_PROTECT_RECURSION_P(entry);
		}
		ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(entry), value_ptr) {
			php_compact_var(eg_active_symbol_table, return_value, value_ptr);
		} ZEND_HASH_FOREACH_END();
	    if (Z_REFCOUNTED_P(entry)) {
			Z_UNPROTECT_RECURSION_P(entry);
		}
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

zend_hash_find_ind という関数で与えられた変数名に紐づく値を取り出して return 用の配列に入れているような実装でした。

具体的にはここら辺です。

if ((value_ptr = zend_hash_find_ind(eg_active_symbol_table, Z_STR_P(entry))) != NULL) {
 ZVAL_DEREF(value_ptr);
 ZVAL_COPY(&data, value_ptr);
 zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
}
1
2
3
4
5

まとめ

これ結構使い勝手いいかも。