PHP 7 內核重構(PHPNG)帶來巨大效能提升,但擴展開發 API 發生重大變更。本文記錄遷移過程中遇到的核心兼容性問題及解決方案,助你避坑。
| 函數 | PHP 5 參數數 | PHP 7 參數數 | 遷移操作 |
|---|---|---|---|
| add_assoc_stringl | 5 | 4 | 刪除最後一個參數 |
| add_assoc_string | 4 | 3 | 刪除最後一個參數 |
| add_next_index_stringl | 4 | 3 | 刪除最後一個參數 |
| add_next_index_string | 3 | 2 | 刪除最後一個參數 |
| RETURN_STRINGL | 3 | 2 | 刪除最後一個參數 |
原因:PHP 7 使用 zend_string 管理字串,長度資訊內嵌,無需額外傳遞。
// 在 #include "php.h" 之前添加
#include
#ifndef INT64_MAX
# define INT64_MAX INT64_C(9223372036854775807)
#endif
#ifndef INT64_MIN
# define INT64_MIN (-INT64_C(9223372036854775807)-1)
#endif
參考 ext/mysqli/mysqli.c 中的 mysqli_objects_new 方法實現。
// PHP 5 風格(堆分配)
zval* sarray_l;
ALLOC_INIT_ZVAL(sarray_l);
array_init(sarray_l);
// PHP 7 風格(棧分配)
zval sarray_l;
array_init(&sarray_l);
PHP 7 採用棧分配減少內存分配開銷,zval 不再是指針。
// PHP 7 簽名(4 參數)
ZEND_API int ZEND_FASTCALL zend_hash_get_current_key_ex(
const HashTable *ht,
zend_string **str_index,
zend_ulong *num_index,
HashPosition *pos
);
// 遷移:刪除原第 3、5 參數
PHP 7 移除 Z_TYPE_PP,僅保留:
Z_TYPE(zval)Z_TYPE_P(zval*)遷移:將 Z_TYPE_PP(pp) 改為 Z_TYPE_P(*pp) 或重構代碼避免雙重指針。
// PHP 7 使用 zend_string 存儲字串
zend_string *str;
char *cstr = ZSTR_VAL(str); // 宏轉換,非直接賦值
IS_BOOLIS_TRUE、IS_FALSEZ_TYPE_P(zval) == IS_TRUE 為 true改用類型判斷:
// 舊:Z_BVAL_P(zval)
// 新:
if (Z_TYPE_P(zval) == IS_TRUE) { /* true */ }
else if (Z_TYPE_P(zval) == IS_FALSE) { /* false */ }
// 新增獲取宏
static inline my_object *my_fetch_object(zend_object *obj) {
return (my_object *)((char*)obj - XtOffsetOf(my_object, std));
}
#define Z_MYOBJ_P(zv) my_fetch_object(Z_OBJ_P(zv))
// 使用:Z_MYOBJ_P(zv) 替代 zend_object_store_get_object(zv)
my_object 為自定義結構體,需包含 zend_object std 作為首字段。
stdint.h 修復 INT64 宏zval 改棧分配,傳遞地址Z_TYPE_PP、IS_BOOL、Z_BVALzend_string 轉換使用 ZSTR_VAL()Z_OBJ_P + 自定義 fetch 宏建議對照 php-src/UPGRADING.INTERNALS 文檔系統遷移,並參考官方擴展(mysqli、pdo、redis 等)遷移提交記錄。