php 有没有办法在不必创建变量的情况下捕获异常?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4820211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is there a way to catch an Exception without having to create a variable?
提问by Matthieu Napoli
In PHP, I sometimes catch some exceptions with try/catch :
在 PHP 中,我有时会使用 try/catch 捕获一些异常:
try {
...
} catch (Exception $e) {
// Nothing, this is normal
}
With that kind of code, I end up with the variable $e
that is created for nothing (lots of resources), and PHP_MD (PHP Mess Detector) creates a warning because of an unused variable.
使用这种代码,我最终$e
会得到一个无用(大量资源)创建的变量,而 PHP_MD(PHP Mess Detector)由于未使用的变量而创建警告。
采纳答案by yivi
Starting with PHP 8, to be released on November 2020, it will be possible to use a non-capturing catch.
从将于 2020 年 11 月发布的 PHP 8 开始,可以使用非捕获捕获。
This is the relevant RFC, which was voted favourably 48-1.
这是相关的 RFC,它以 48-1 的票数投了赞成票。
Now it will be possible to do something like this:
现在可以做这样的事情:
try {
readFile($file);
} catch (FileDoesNotExist) {
echo "File does not exist";
} catch (UnauthorizedAccess) {
echo "User does not have the appropriate permissions to access the file";
log("User attempted to access $file");
}
With this, for some edge cases where the exception details are not relevant and exception type already provides all the necessary context, it will be possible to catch the exception without creating a new variable.
这样,对于异常详细信息不相关且异常类型已经提供所有必要上下文的某些边缘情况,可以在不创建新变量的情况下捕获异常。
回答by TarranJones
PHP 5,7
菲律宾比索 5,7
No, but you can unset it.
不,但您可以取消设置。
try {
...
} catch (Exception $e) {
// Nothing, this is normal
unset($e);
}
If it is PHPMD causing this issue then you can suppress the warning.
如果是 PHPMD 导致此问题,那么您可以取消警告。
class Bar {
/**
* This will suppress UnusedLocalVariable
* warnings in this method
*
* @SuppressWarnings(PHPMD.UnusedLocalVariable)
*/
public function foo() {
try {
...
} catch (Exception $e) {
// Nothing, this is normal
unset($e);
}
}
}
I'm assuming you are only catching the exception because you need to not because you want to.
With PHP 5,7 you have to use a catch
if you want to use try
and if you use a catch
you have to declare a variable.
我假设您只是在捕获异常,因为您需要而不是因为您想要。在 PHP 5,7 中,catch
如果要使用try
,则必须使用 a,如果使用 a catch
,则必须声明一个变量。
回答by Wouter Florijn
I disagree fundamentally with Marc B's and Artefacto's answers. There are cases where ommitting the catch is better or even the only option. Especially when using external libraries (where you have no control over what exceptions are thrown) and/or async operations.
我从根本上不同意 Marc B 和 Artefacto 的回答。在某些情况下,忽略捕获更好,甚至是唯一的选择。特别是在使用外部库(您无法控制抛出的异常)和/或异步操作时。
For example:
例如:
I want to create a file only if it doesn't exist yet. I'm using an external I/O library. Imagine it has File::exists($fileName)
and File::create($fileName)
methods.
我只想创建一个文件,如果它还不存在。我正在使用外部 I/O 库。想象一下它有File::exists($fileName)
和File::create($fileName)
方法。
Option 1 (if ommitting the catch was possible):
选项 1(如果可以省略捕获):
try {
File::create($fileName);
}
// Go on with the rest of the code.
Option 2 (without try/catch):
选项 2(不带 try/catch):
if (!File::exists($fileName))
File::create($fileName);
Here, option 1 is perfectly valid, since option 2 has two important issues:
在这里,选项 1 完全有效,因为选项 2 有两个重要问题:
- If multiple threads are running and going through this code section at the same time, it could be that thread A first checks if the file exists. Next, thread B checks if the file exists. They both find that it doesn't exist. Thread A creates the file. Thread B then attempts to create it again and throws an exception even though you're using the if check.
- It's very likely that the library itself already performs the
!File::exists($fileName)
check. Therefore you're wasting a call that is already made.
- 如果多个线程正在运行并同时执行此代码部分,则可能是线程 A 首先检查文件是否存在。接下来,线程 B 检查文件是否存在。他们都发现它不存在。线程 A 创建文件。线程 B 然后尝试再次创建它并抛出异常,即使您正在使用 if 检查。
- 很可能图书馆本身已经执行了
!File::exists($fileName)
检查。因此,您正在浪费已经拨打的电话。
Note that if File::create
throws other exceptions that might be unexpected it would be good to catch those.
请注意,如果File::create
抛出其他可能出乎意料的异常,最好捕获这些异常。
Conclusion
结论
Stating that something is nevera good idea, is almost nevera good idea. There are always exceptions (hehe) to the rule. Like any convention or design pattern, it's just a rule of thumb meant to help less experienced developers make the right decision.
说某件事永远不是一个好主意,几乎从来都不是一个好主意。规则总是有例外的(呵呵)。像任何约定或设计模式一样,它只是一个经验法则,旨在帮助经验不足的开发人员做出正确的决定。
回答by Marc B
That's the whole point of exceptions - you can have multiple different catch blocks to catch any exceptions you'd want to handle. The exception's data has to be assigned somewhere, hence the variable. You could just do something like unset($e)
inside the catch block if you really don't want to see those warnings... or disable the warnings (generally a bad idea).
这就是异常的全部意义——您可以有多个不同的 catch 块来捕获您想要处理的任何异常。异常的数据必须在某处分配,因此是变量。unset($e)
如果你真的不想看到那些警告,你可以在 catch 块内做一些事情......或者禁用警告(通常是一个坏主意)。
回答by Artefacto
No.
不。
In any case, it's generally a bad idea to catch an exception and do nothing; exceptions exist precisely to force you to handle the exceptional circumstance (otherwise execution is aborted), so it's comprehensible the language doesn't facilitate such a use case.
在任何情况下,捕获异常而什么都不做通常是个坏主意;异常的存在正是为了迫使您处理异常情况(否则执行将中止),因此可以理解该语言不利于此类用例。
回答by SanePumpkins
Exceptions are not only used for exceptional circumstances.
异常不仅仅用于特殊情况。
This scenario actually uses exceptions to make sure the user is logged out. At this point in the script it's very resource expensive to figure out what data should be pruned so it's actually faster to just prune it all and catch the exceptions.
此场景实际上使用异常来确保用户已注销。在脚本的这一点上,确定应该修剪哪些数据是非常耗费资源的,因此实际上只修剪所有数据并捕获异常会更快。
try {
GDS::$DB->exec('DELETE FROM sessions WHERE session_id = ' . session_id());
GDS::$DB->exec('DELETE FROM sessions WHERE user_id = ' . $this->data['user_id']);
} catch(PDOException $ex) {}
session_regenerate_id(true);
setcookie('bis_[user_id]', 0, time() - 1, null, null, false, true);
setcookie('bis_[session_start]', 0, time() - 1, null, null, false, true);
setcookie('bis_[session_time]', 0, time() - 1, null, null, false, true);