Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PHP评估和捕获错误(尽可能多)_Php_Exception_Parsing_Eval - Fatal编程技术网

PHP评估和捕获错误(尽可能多)

PHP评估和捕获错误(尽可能多),php,exception,parsing,eval,Php,Exception,Parsing,Eval,免责声明;我完全了解eval的缺陷和“弊病”,包括但不限于:性能问题、安全性、可移植性等 问题 正在阅读有关评估的PHP手册 eval()返回NULL,除非返回为空 在求值代码中调用,其中 案例传递给return的值为 返回。如果中存在分析错误 求值代码eval()返回 错误和执行以下内容 代码正常继续。事实并非如此 可能在中捕获分析错误 使用set\u error\u handler()进行eval() 简而言之,除了返回false之外,没有错误捕获,这非常有用,但我相信eI可以做得更好 原因

免责声明;我完全了解eval的缺陷和“弊病”,包括但不限于:性能问题、安全性、可移植性等

问题

正在阅读有关评估的PHP手册

eval()返回NULL,除非返回为空 在求值代码中调用,其中 案例传递给return的值为 返回。如果中存在分析错误 求值代码eval()返回 错误和执行以下内容 代码正常继续。事实并非如此 可能在中捕获分析错误 使用set\u error\u handler()进行eval()

简而言之,除了返回false之外,没有错误捕获,这非常有用,但我相信eI可以做得更好

原因

我正在使用的站点功能的一部分依赖于执行表达式。我不想通过沙盒或执行模块的路径,所以我结束了使用eval。在你大喊“如果客户变坏了怎么办?!”之前,要知道客户是非常值得信任的;他不想破坏自己的网站,任何访问此功能的人几乎都拥有服务器,不管eval如何

客户机知道Excel中的表达式,解释这些小差异并不是问题,但是,具有某种形式的警告几乎是标准功能

这就是我到目前为止所做的:

define('CR',chr(13));
define('LF',chr(10));

function test($cond=''){
    $cond=trim($cond);
    if($cond=='')return 'Success (condition was empty).'; $result=false;
    $cond='$result = '.str_replace(array(CR,LF),' ',$cond).';';
    try {
        $success=eval($cond);
        if($success===false)return 'Error: could not run expression.';
        return 'Success (condition return '.($result?'true':'false').').';
    }catch(Exception $e){
        return 'Error: exception '.get_class($e).', '.$e->getMessage().'.';
    }
}
注释

  • 函数在任何事件中都返回消息字符串
  • 代码表达式应该是一行PHP,没有PHP标记,也没有结尾分号
  • 新行将转换为空间
  • 添加了一个变量来包含结果(表达式应返回true或false,并且为了不与eval的返回冲突,使用了一个temp变量。)
那么,您会添加什么来进一步帮助用户呢?是否有任何进一步的解析功能可以更好地查明可能的错误/问题

Chris。

因为PHP 7 eval()将生成语法错误的异常:

try {
    $result = eval($code);
} catch (ParseError $e) {
    // Report error somehow
}
在PHP 5中,eval()将生成一个解析错误,该错误的特殊情况是不中止执行(解析错误通常会这样做)。但是,它也不能通过错误处理程序捕获。一种可能是捕获打印的错误消息,假设
display\u errors=1

ob_start();
$result = eval($code);
if ('' !== $error = ob_get_clean()) {
    // Report error somehow
}

对于我的问题,我找到了一个好的选择/答案

首先,让我先说,当我设置错误报告(E_ALL)时,nikic的建议有效;通知显示在PHP输出中,感谢OB,它们可以被捕获

接下来,我发现了以下非常有用的代码:

/**
 * Check the syntax of some PHP code.
 * @param string $code PHP code to check.
 * @return boolean|array If false, then check was successful, otherwise an array(message,line) of errors is returned.
 */
function php_syntax_error($code){
    if(!defined("CR"))
        define("CR","\r");
    if(!defined("LF"))
        define("LF","\n") ;
    if(!defined("CRLF"))
        define("CRLF","\r\n") ;
    $braces=0;
    $inString=0;
    foreach (token_get_all('<?php ' . $code) as $token) {
        if (is_array($token)) {
            switch ($token[0]) {
                case T_CURLY_OPEN:
                case T_DOLLAR_OPEN_CURLY_BRACES:
                case T_START_HEREDOC: ++$inString; break;
                case T_END_HEREDOC:   --$inString; break;
            }
        } else if ($inString & 1) {
            switch ($token) {
                case '`': case '\'':
                case '"': --$inString; break;
            }
        } else {
            switch ($token) {
                case '`': case '\'':
                case '"': ++$inString; break;
                case '{': ++$braces; break;
                case '}':
                    if ($inString) {
                        --$inString;
                    } else {
                        --$braces;
                        if ($braces < 0) break 2;
                    }
                    break;
            }
        }
    }
    $inString = @ini_set('log_errors', false);
    $token = @ini_set('display_errors', true);
    ob_start();
    $code = substr($code, strlen('<?php '));
    $braces || $code = "if(0){{$code}\n}";
    if (eval($code) === false) {
        if ($braces) {
            $braces = PHP_INT_MAX;
        } else {
            false !== strpos($code,CR) && $code = strtr(str_replace(CRLF,LF,$code),CR,LF);
            $braces = substr_count($code,LF);
        }
        $code = ob_get_clean();
        $code = strip_tags($code);
        if (preg_match("'syntax error, (.+) in .+ on line (\d+)$'s", $code, $code)) {
            $code[2] = (int) $code[2];
            $code = $code[2] <= $braces
                ? array($code[1], $code[2])
                : array('unexpected $end' . substr($code[1], 14), $braces);
        } else $code = array('syntax error', 0);
    } else {
        ob_end_clean();
        $code = false;
    }
    @ini_set('display_errors', $token);
    @ini_set('log_errors', $inString);
    return $code;
}
/**
*检查一些PHP代码的语法。
*@param string$code要检查的PHP代码。
*@return boolean | array如果为false,则检查成功,否则返回错误数组(消息、行)。
*/
函数php_语法_错误($code){
如果(!定义(“CR”))
定义(“CR”,“r”);
如果(!已定义(“LF”))
定义(“LF”、“\n”);
如果(!已定义(“CRLF”))
定义(“CRLF”,“\r\n”);
$brages=0;
$inString=0;

foreach(token_get_all(“您也可以尝试以下方法:

$filePath = '/tmp/tmp_eval'.mt_rand();
file_put_contents($filePath, $evalCode);
register_shutdown_function('unlink', $filePath);
require($filePath);

因此,$evalCode中的任何错误都将由错误处理程序处理。

如何测试eval()中的解析错误:


如果
$result==false
$evalcode
有一个解析错误,并且不执行“return true”部分。显然
$evalcode
不能返回本身的内容,但是使用这个技巧,您可以有效地测试表达式中的解析错误…

好消息:
eval()
now*如果评估的代码无效,则抛出
ParseError
异常:

try
{
    eval("Oops :-o");
}
catch (ParseError $err)
{
    echo "YAY! ERROR CAPTURED: $err";
}


*好吧,有一段时间…;)

如果你能提供更多关于你将使用什么“表达式”的反馈,也许我们可以提供更多帮助。我可以想出一些很好的标记来验证用户输入;)普通PHP代码?我计划允许对PHP的完全访问,但定义函数和类可能是个例外,这是不需要的。@Sz。尽管如此,我还是建议现在使用(10年时还没有)是的,我确实定义了它们,很抱歉没有提及。修复了上面的代码。至于异常,我很确定这两者都没有,但是,在可能添加了异常之后,这段代码将来可能会失败,所以不管怎样处理它们都不会有任何伤害。我无法找到
check\u syntax
php\u check\u syntax
在5.0.5中被删除他们希望您执行类似的操作(“echo”
!=
运算符的优先级高于
=
。您需要添加括号:
(“”!=($error=ob\u get\u clean())
@François如果赋值在RHS上就不会。这就是为什么在这里使用Yoda条件。哇,这看起来不错。我又学到了一点新东西:
break
可以有一个参数!我稍后会看一看这段代码以真正理解它的作用。只需注意:如果代码中有严重的解析错误,
token\u get\u all
可以自己输出错误,例如,如果您在源代码中使用“\”(在PHP中,它非常好。遗憾的是,它仍然不能提供防止错误函数调用的保护,例如函数名中的简单拼写错误。PHP应该真正考虑在eval()中捕获致命错误)非常聪明的主意!我还没有测试过它,但我会的。你不能在
eval
'd代码中捕获解析错误!它只会停止脚本的执行。这对我来说非常有效,即使我的eval()返回一个值。我有
$value=eval(“返回”$evalcode.”返回false;
,然后
如果($value==false)返回(“错误:“.$evalcode);
当然这意味着evalcode在正常情况下永远不能返回false。但这适合我的使用。
try
{
    eval("Oops :-o");
}
catch (ParseError $err)
{
    echo "YAY! ERROR CAPTURED: $err";
}