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会修复它。无法重现错误。什么可能导致这个问题?无法弄清楚这一点。
最近有一点需要注意,这个错误只发生在使用Cache的Pages上。之前它会发生在每一页上。
我们正在使用memcached和opcache(PHP 5.5)。奇怪的是我们不需要清除memcached数据来解决问题,只有apache重启,这只会清除" opcache"。
答案 0 :(得分:3)
错误
您看到此错误意味着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。因此,可能是因为您正在评估方法中的某些代码,这会导致编译文件损坏 - 但我无法肯定地说。另一件事 - 它可能是bug,它位于opcache
扩展内。但无论如何,原因是 - 错误的编译导致VM尝试执行编译脚本时出现此类错误。并且,因为它可以通过清除opcache来解决(因此,web-server resart) - 我认为原因是 - 它是一个bug。
所以,TL; DR - 我不能说肯定的原因,但可以给出一些指导。由于这只是评论的过多,所以发布为答案