zend_class_entry 是类定义的元数据容器,非对象模板;它存储类名、方法表、属性信息等元数据,供引擎解析类结构但不参与实例化,所有实例共享同一份结构。

zend_class_entry 是类定义的元数据容器,不是对象模板
它不参与实例化过程,也不直接对应 new 出来的对象内存。你写 class User {},PHP 编译后生成的只是一个 zend_class_entry 结构体,存于请求期的全局符号表里,所有 User 实例共享这份结构。
常见误解是把它当成 C++ 的 class 定义 —— 实际上它更像一张“说明书”:告诉引擎这个类叫什么、有哪些方法、属性怎么存、父类是谁、能不能 new……但不包含任何运行时数据。
关键字段分三类:标识、行为、存储
按用途可粗略划为:
-
标识信息:
name(类名字符串)、type(ZEND_USER_CLASS或ZEND_INTERNAL_CLASS)、parent(父类指针)、interfaces(实现的接口链表) -
行为描述:
function_table(方法名 →zend_function*映射哈希表)、constructor/destructor等魔术方法指针、ce_flags(如ZEND_ACC_FINAL、ZEND_ACC_INTERFACE) -
存储布局:
default_properties_table(public 属性默认值数组)、properties_info(每个属性的类型/可见性/是否初始化等元信息)、static_members_table(静态属性实际存储区)
interface 的 zend_class_entry 特别轻量
接口定义如 interface PaymentService 也会生成 zend_class_entry,但它和类有本质区别:
立即学习“PHP免费学习笔记(深入)”;
-
function_table里只存方法签名,没有函数指针(handler为空) -
default_properties_table为 NULL,create_object处理器被设为 NULL - 引擎在
new时检查ce->type == ZEND_ACC_INTERFACE,立刻报Fatal error: Cannot instantiate interface - 类型提示如
PaymentService $s的校验,仅比对目标对象的ce是否在其实现的接口链表中
扩展开发中必须显式注册
写 PHP 扩展时,zend_class_entry 不会自动生效,必须手动注册进引擎:
- 先用
INIT_CLASS_ENTRY初始化结构体,填入类名和方法表 - 调用
zend_register_internal_class注册,返回zend_class_entry*指针 - 注册后才能在 PHP 用户代码里
new它;未注册则报Class 'MyClass' not found - 若需设置 final、abstract 等标志,得在注册后修改
ce->ce_flags,比如ce->ce_flags |= ZEND_ACC_FINAL_CLASS
真正容易被忽略的是:zend_class_entry 本身不带生命周期管理 —— 它在模块加载时注册,在请求结束或模块卸载时才释放。如果在 MINIT 阶段漏掉 zend_register_internal_class,整个类就不可见,且无任何编译期提示。



















