简体   繁体   English

有没有比处理@更好的方法来处理预期的错误?

[英]Is there a better way to handle expected errors than doing `@`?

I have a script that checks if a port is accessible on an IP address. 我有一个脚本,用于检查IP地址上是否可访问端口。 So whether I choose to do that with file_get_contents or with fsockopen , the concept stays the same, which is that I have to call either of those functions in order to get my result. 因此,无论我选择使用file_get_contents还是fsockopen ,概念都保持不变,这就是我必须调用这些函数中的任何一个才能获得结果。 Eg, there is no equivalent to file_exists which would "guarantee" that calling file_get_contents would not generate an error when calling a URL. 例如,没有与file_exists等效的东西,它可以“保证”调用URL时调用file_get_contents不会产生错误。

What bugs me in this kind of a scenario, is that an error is a completely acceptable part in the flow of the program, and therefore shouldn't be treated as other ("actual") errors across my application. 在这种情况下令我感到困扰的是,错误是程序流程中完全可以接受的部分,因此不应将其视为整个应用程序中的其他(“实际”)错误。 Because what I usually have running is a custom error handler, for any occasion where something unexpected would fail, which writes the error message in a log file, and then displays a big 404-like error page. 因为我通常运行的是自定义错误处理程序,所以在任何意外情况失败的情况下,该错误处理都会在日志文件中写入错误消息,然后显示类似404的大错误页面。 Which means that in this case, I have to do a restore_error_handler , in order to be able to do @file_get_contents without a massive error screen appearing, in order to check if the result of it is false . 这意味着在这种情况下,我必须执行restore_error_handler ,以便能够执行@file_get_contents而不会出现大量错误屏幕,以便检查其结果是否为false

So currently that's how it works, and the output is correct, but the approach seems wrong. 所以目前就是这样,并且输出正确,但是这种方法似乎是错误的。 What I am wondering is, is there a prettier way of solving this type of a scenario? 我想知道的是,有没有更漂亮的方式来解决这种情况? One that wouldn't require me to unset something that that is application-wide, and that would resemble a try-catch approach more. 它不需要我取消整个应用程序范围内的设置,并且更像是try-catch方法。

I'll start with the very best option, even though it doesn't actually exist yet. 我将从最好的选项开始,即使它实际上还不存在。

When PHP 7 is released (currently at beta 3, so final release should be some time in the next couple of months), it will feature a completely re-written error handling system. 当PHP 7发布时(当前为beta 3,因此最终发布应在接下来的几个月内进行),它将具有完全重写的错误处理系统。

The new PHP 7 error handler turns all the old PHP errors into a new type of exception. 新的PHP 7错误处理程序将所有旧的PHP错误变成一种新的异常类型。 This means that you can simply use try ... catch to handle them, just like other exceptions. 这意味着您可以像其他异常一样,简单地使用try ... catch来处理它们。 This will simplify PHP error handling enormously, and for me is one of the major selling points of moving up to PHP 7 as soon as possible after it's released. 这将极大地简化PHP错误处理,对我来说,这是在PHP 7发布后尽快升级到PHP 7的主要卖点之一。

However, it isn't released yet, and you may not be able to / willing to upgrade to it immediately anyway, so here are the other options: 但是,它尚未发布,而且您可能仍然无法/不愿立即升级到它,因此这里有其他选项:

  1. Switch to the alternative OO classes. 切换到替代的OO类。
    Many PHP functions have object oriented alternatives which throw exceptions rather than old-style errors. 许多PHP函数具有面向对象的替代方案,这些替代方案引发异常而不是旧式错误。 For example, you specified file_get_contents() in your question; 例如,您在问题中指定了file_get_contents() these can be replaced with calls to the SplFileObject class . 这些可以替换为SplFileObject类的调用。 fsockopen() is often used for making http calls, so maybe swap that code out for the Guzzle library. fsockopen()通常用于进行http调用,因此也许可以将该代码换成Guzzle库。 And so on. 等等。 There's usually a way of doing things that avoids having to rely on the old functions at all. 通常情况下,有一种方法可以避免完全依赖旧功能。

  2. If you really do need to rely on the old functions, and you really can't find a way to check for potential errors before calling them, then you need to consider using the old error handling function set_error_handler() . 如果确实需要依赖旧的函数,并且在调用它们之前确实找不到寻找潜在错误的方法,那么您需要考虑使用旧的错误处理函数set_error_handler() This function allows you to specify a function which will be called when an error occurs. 此函数使您可以指定发生错误时将调用的函数。 Once in the error handling function, you can do what is necessary to handle it and either return (in which case the original code will contine at the next line) or die gracefully if the error can't be recovered from. 进入错误处理功能后,您可以执行处理该错误所需的操作,然后返回(在这种情况下,原始代码将在下一行建立),或者如果无法从中恢复错误,则正常终止。

Ultimately, though, you're absolutely right -- PHP errors are a bit of a dogs breakfast, and really not easy to work with. 但是,最终,您绝对是正确的-PHP错误有点令人难以忍受,并且使用起来并不容易。 The @ operator stinks, but occasionally there really isn't any alternative to it. @运算符很臭,但有时确实没有其他选择。 I haven't found myself using one in a long time now, so you really shouldn't need it, but I do concede that it may be necessary from time to time simply because PHP doesn't offer anything better. 我已经很长时间没有发现自己使用它了,所以您确实不需要它,但是我承认有时可能只是因为PHP没有提供更好的功能而有必要。

That will change with PHP 7; PHP 7将改变这种情况; the error handling is one of many things which are being drastically improved. 错误处理是正在大大改进的许多事情之一。 I'm looking forward to its release. 我期待它的发布。

What I am wondering is, is there a prettier way of solving this type of a scenario? 我想知道的是,有没有更漂亮的方式来解决这种情况? One that wouldn't require me to unset something that that is application-wide, and that would resemble a try-catch approach more. 它不需要我取消整个应用程序范围内的设置,并且更像是try-catch方法。

Whether this is "prettier" is opinion-based, but you can convert all errors to exception in your custom error handler, which allows you to actually catch them: 这是否“漂亮”是基于意见的,但是您可以在自定义错误处理程序中将所有错误转换为异常,这使您可以实际catch它们:

set_error_handler(function($num, $msg, $file, $line)
{
    // Convert to exceptions
    throw new ErrorException($msg, 0, $num, $file, $line);
});
set_exception_handler(function($e)
{
    // Print or log to file
    echo get_class($e).': '.$e->getMessage().' ['.$e->getFile().':'.$e->getLine().']';
});

try
{
    // Will be caught
    echo array();
}
catch(ErrorException $e) {}

// Will not be caught
echo array();

[ Demo ] [ 演示 ]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM