public function evaluateExpression($_expression_,$_data_=array())
{
if(is_string($_expression_))
{
extract($_data_);
return eval('return '.$_expression_.';');
}
else
{
$_data_[]=$this;
return call_user_func_array($_expression_, $_data_);
}
}
我在此方法的第一行收到此错误。我在这里没有看到任何打字提示。上面的代码来自 Yii Framework 的内部文件。 (yiilite.php:L842)
该错误是间歇性的,重新启动 apache 即可修复该错误。也无法重现该错误。什么会导致这个问题?无法弄清楚这一点。
最近需要注意的一件事是,此错误仅发生在使用缓存的页面上。早些时候它会发生在每个页面上。
我们正在使用 memcached 和 opcache ( PHP 5.5 )。奇怪的是我们不需要清除memcached数据来解决这个问题,只需要重新启动apache,这只会清除“opcache”。
最佳答案
错误
您看到的这个错误意味着 PHP 不是在解释阶段失败,而是在执行阶段失败。如您所知,PHP 分两步执行 - 首先,将脚本编译为操作码,然后使用虚拟机(通常是 ZendVM)执行这些操作码。我们可以确定执行阶段失败的原因在于 zend_verify_arg_type()
,这是执行实现的一部分:
static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
{
//I stripped some lines here (insignificant)
if (cur_arg_info->class_name) {
/* do the things, when typehinted is class name */
} else if (cur_arg_info->type_hint) {
/* your case, typehint wasn't class name */
switch(cur_arg_info->type_hint) {
case IS_ARRAY:
//I stripped some lines here (insignificant)
break;
case IS_CALLABLE:
//I stripped some lines here (insignificant)
break;
default: //<---- You error is here
zend_error(E_ERROR, "Unknown typehint");
}
}
return 1;
}
如您所见,对于发生此错误,PHP 应该将 typehint 视为不是类名,同时将其视为“未知”的内容。这就是为什么您无法在常规情况下重现错误 - 因为 PHP 会首先尝试将 typehint 视为类名(因此,错误将类似于 “传递给 {function()} 的参数 {N} 必须是一个实例{classname}")
原因
因此,虽然在正常执行机制中不会出现此类错误,但您仍然可以获得一些损坏的编译文件 - 另一个提示是您正在使用 opcache。因此,这可能是因为您正在评估方法中的某些代码,这可能会导致编译文件损坏 - 但我不能肯定地说。另一件事 - 它可能是错误,它位于 opcache 扩展内部。但无论如何,原因是 - 当虚拟机尝试执行编译的脚本时,错误的编译会导致此类错误。而且,由于它可以通过清除 opcache 来解决(因此,网络服务器重新启动) - 我认为原因是 - 这是一个错误。
所以,TL;DR - 我不能确定原因,但可以提供一些指导。由于这对于仅仅评论来说太多了,因此作为答案发布
关于PHP fatal error : Unknown typehint,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25486666/