PHP 7底层:查找‘must be an instance’错误生成位置及__construct参数解析
嘿,刚好我之前挖过PHP 7的类型检查和构造函数执行逻辑,给你精准定位关键代码位置:
1. "must be an instance of" 错误信息的生成逻辑
这个错误属于类型不匹配错误,是在参数类型验证失败时抛出的。你可以在这两个核心文件里找到相关逻辑:
错误字符串的生成点:在
Zend/zend_exceptions.c中,zend_throw_type_error函数负责拼接并抛出这个错误。关键代码片段如下:zend_throw_type_error("Argument %d passed to %s() must be an instance of %s, %s given", arg_num, func_name, expected_type_name, actual_type_name);当参数的实际类型和声明的类类型不匹配时,PHP的执行器会调用这个函数抛出错误。
触发错误的类型检查逻辑:参数类型验证主要在
Zend/zend_types.c中的zend_verify_arg_type函数里完成。这个函数会对比传入参数的类型和方法声明的参数类型,如果是类实例类型不匹配,就会调用上面的错误抛出函数。
2. __construct 的参数解析流程
构造函数的参数解析和普通方法遵循同样的逻辑,分为编译和执行两个阶段:
编译阶段:参数信息的解析与存储
在Zend/zend_compile.c中,当编译器解析类的__construct方法时,会通过zend_compile_method函数处理方法的参数列表,将参数的类型、名称等信息存储到方法的zend_function结构体中,后续执行时会用到这些信息做验证。执行阶段:参数的传递与验证
当代码中执行new A($obj)这类创建对象的操作时,PHP会触发ZEND_NEWopcode。对应的处理逻辑在Zend/zend_execute.c的zend_do_new函数中:- 先解析传入的所有参数,转换为PHP内部的zval结构;
- 调用构造函数前,会先调用前面提到的
zend_verify_arg_type逐个验证参数类型; - 如果类型验证失败,就会抛出你看到的那个类型错误。
简单来说,构造函数的参数解析是和方法调用的参数处理逻辑统一的,只是在对象实例化的流程中被触发。
内容的提问来源于stack exchange,提问作者Eugene Kapelko

