PHP 核心函数,在错误发生时抛出异常而不是返回 FALSE


README

Latest Stable Version Total Downloads Latest Unstable Version License Build Status Continuous Integration codecov

Safe PHP

一组核心 PHP 函数被重写,以便在遇到错误时抛出异常而不是返回 false

问题

大多数 PHP 核心函数都是在添加异常处理之前编写的。因此,大多数 PHP 函数不会抛出异常。相反,在出现错误时它们会返回 false

但我们大多数人太懒惰了,以至于不想逐个检查每个核心 PHP 函数的每个返回值。

// This code is incorrect. Twice.
// "file_get_contents" can return false if the file does not exist
// "json_decode" can return false if the file content is not valid JSON
$content = file_get_contents('foobar.json');
$foobar = json_decode($content);

这段代码的正确版本应该是

$content = file_get_contents('foobar.json');
if ($content === false) {
    throw new FileLoadingException('Could not load file foobar.json');
}
$foobar = json_decode($content);
if (json_last_error() !== JSON_ERROR_NONE) {
    throw new FileLoadingException('foobar.json does not contain valid JSON: '.json_last_error_msg());
}

显然,虽然这个片段是正确的,但它不那么容易阅读。

解决方案

输入 thecodingmachine/safe 也称为 Safe-PHP。

Safe-PHP 重新声明了所有核心 PHP 函数。新的 PHP 函数的行为与旧函数完全一样,只是在遇到错误时适当地抛出异常。这些“安全”函数的名称与核心 PHP 函数相同,但它们位于 Safe 命名空间中。

use function Safe\file_get_contents;
use function Safe\json_decode;

// This code is both safe and simple!
$content = file_get_contents('foobar.json');
$foobar = json_decode($content);

所有可以在错误时返回 false 的 PHP 函数都是 Safe 的一部分。此外,Safe 还提供了两个 'Safe' 类:Safe\DateTimeSafe\DateTimeImmutable,其方法将抛出异常而不是返回 false。

PHPStan 集成

是的...但我必须为应用程序的每个文件显式地考虑导入函数的“安全”版本。我确信我会忘记一些“use function”语句!

不用担心!thecodingmachine/safe 伴随着一个 PHPStan 规则。

之前没有听说过 PHPStan?去看看吧,它是一个令人惊叹的 PHP 代码分析器。

只需在 PHPStan 设置中安装 Safe 规则(在“安装”部分中解释),PHPStan 就会每次告诉你何时使用了“不安全”的函数。

下面的代码将触发此警告

$content = file_get_contents('foobar.json');

函数 file_get_contents 不安全使用。它可以返回 FALSE 而不是抛出异常。请将 'use function Safe\file_get_contents;' 添加到文件的开始部分以使用由 'thecodingmachine/safe' 库提供的版本。

安装

使用 composer 安装 Safe-PHP

$ composer require thecodingmachine/safe

强烈推荐:安装 PHPStan 和 PHPStan 扩展

$ composer require --dev thecodingmachine/phpstan-safe-rule

现在,编辑你的 phpstan.neon 文件并添加以下规则

includes:
    - vendor/thecodingmachine/phpstan-safe-rule/phpstan-safe-rule.neon

自动重构

你有大量的遗留代码库,并想在项目中使用“Safe-PHP”函数?PHPStan 会帮助你找到这些函数,但逐个更改函数的命名空间可能是一项繁琐的任务。

幸运的是,Safe 随带一个“Rector”配置文件。Rector 是一个命令行工具,可以即时重构你的应用程序。

运行

$ composer require --dev rector/rector

安装 rector/rector

运行

vendor/bin/rector process src/ --config vendor/thecodingmachine/safe/rector-migrate.php

运行 rector/rector

注意:不要忘记将“src/”替换为你的源目录路径。

重要:重构只执行“愚蠢”的函数替换。它不会修改处理“false”返回值的方式。所以如果你的代码已经执行了错误处理,你将需要手动处理。

特别是,你应该寻找已经执行的错误处理,如下

if (!mkdir($dirPath)) {
    // Do something on error
}

此代码将被 Rector 重构为

if (!\Safe\mkdir($dirPath)) {
    // Do something on error
}

然后你应该(手动)将其重构为

try {
    \Safe\mkdir($dirPath));
} catch (\Safe\FilesystemException $e) {
    // Do something on error
}

性能影响

Safe 在每个请求中从大约85个文件中加载1000+个函数。然而,这种加载对性能的影响非常低。

如果您担心,使用Safe会在每个请求中“花费”大约700µs。性能部分包含了更多关于我们如何测试Safe性能影响的信息。

了解更多

如果您想了解更多关于触发Safe-PHP开发的信息,请阅读TheCodingMachine博客上的发布文章

贡献

包含所有函数的文件是从PHP文档自动生成的。阅读CONTRIBUTING.md文件,了解如何重新生成这些文件以及如何为此库做出贡献。