bakame/aide-error

一个用于处理PHP函数错误的简单类

0.1.0 2023-12-09 05:38 UTC

This package is auto-updated.

Last update: 2024-09-22 11:39:09 UTC


README

一个用于帮助处理PHP错误报告的 cloak 系统。

注意

aide的错误子模块。
⚠️ 这是一个子模块,对于 pull request 和问题,请访问: https://github.com/bakame-php/aide

安装

Composer

composer require bakame-php/aide-error

系统要求

您需要

  • PHP >= 8.1,但推荐使用最新的稳定版PHP

用法

传统上,正确处理PHP函数的错误有两种(2)种方法。要么您使用@来抑制错误,这是不建议的;要么您需要围绕set_error_handlerrestore_error_handler添加一些样板代码。

Bakame\Aide\Error\Cloak实用类通过为您做繁重的工作来帮助您减轻这种负担。

<?php

use Bakame\Aide\Error\Cloak;

//using the @ suppression operator
$res = @touch('/foo'); // bad and not recommended

//using error handler
set_error_handler(fn (int $errno, string $errstr, string $errfile = null, int $errline = null) {
    if (!(error_reporting() & $errno)) {
        // This error code is not included in error_reporting
        return;
    }

    throw new \ErrorException($errstr, 0, $errno, $errfile, $errline);
}, E_WARNING);
$res = touch('/foo'); 
restore_error_handler();
// better but having to write this everytime is overkill
// and you have little control

//using Cloak
$touch = Cloak::warning(touch(...));
$res = $touch('/foo');
$touch->errors();
// returns a CloakedErrors instance
// the instance is empty on success
// otherwise contains all the \ErrorException
// generated during the closure execution

您可以通过全局代码库来控制其行为

<?php

use Bakame\Aide\Error\Cloak;

Cloak::throwOnError();

try {
    $touch = Cloak::warning(touch(...));
} catch (ErrorException $exception)
}

或者您可以选择为特定的调用特别更改其默认行为。

<?php

use Bakame\Aide\Error\Cloak;

Cloak::throwOnError(); // by default calls via Cloak should throw

if (!$touch = Cloak::warning(touch(...), Cloak::SILENT)) {
    // errors are still available via the `errors` method
    // but throwing will not happen
    $touch->errors();
}

可用的属性和方法

访问错误

要访问存储在实例中的错误,您需要调用Cloak::errors方法,这将返回一个CloakedErrors实例。此容器允许您访问在回调的最后一次执行期间生成的所有ErrorException。如果在上一次类执行期间没有发生错误,则CloakedErrors实例将为空。

$touch = Cloak::all(touch(...));
$touch('/foobar');
$errors = $touch->errors(); // $errors is a CloakedErrors instance
$errors->isEmpty(); //true if the execution generated 0 ErrorException; false otherwise
foreach ($errors as $error) {
    $error; //ErrorException instances ordered from the newest to the oldest one.
}
$errors->first(); // the oldest ErrorException
$errors->last();  // the newest ErrorException
$errors->get(2); 
$errors->get(-2);
// returns any of the ErrorException and accept negative index.
// the three (3) methods will return `null` if no exception
// exists for the specified offset

控制是否抛出错误。

该类的一般行为由两个(2)个静态方法控制。在所有情况下,如果发生错误,它将被转换为ErrorException并通过Cloak::errors方法使其可访问。区别在于

  • Cloak::throwOnError:每个实例都会在第一个错误上抛出;
  • Cloak::silentOnError:不会抛出任何异常;

注意

为了尊重PHP的行为,Cloak默认使用Cloak::silentOnError

命名构造函数

为了方便使用,添加了命名构造函数

<?php
use Bakame\Aide\Error\Cloak;

Cloak::env(); // will use the current environment error reporting value
// and one for each error reporting level that exists in PHP
Cloak::all();
Cloak::error();
Cloak::warning();
Cloak::notice();
Cloak::deprecated();
Cloak::userError();
Cloak::userWarning();
Cloak::userNotice();
Cloak::userDeprecated();
// some Error reporting will never get triggered
// they exist for completeness but won't be usable.

它们都具有相同的签名

static method(Closure $callback, int $onError = Cloak::OBEY);

$onError参数用于调整实例在错误时的行为

  • Cloak::THROW将覆盖一般行为并强制抛出异常(如果可用)
  • Cloak::SILENT将覆盖一般行为并静默错误(如果存在)
  • Cloak::OBEY将遵守当前的一般行为。

如果您确实需要其他更精细的错误级别,您仍然可以使用如下所示的构造函数

<?php
use Bakame\Aide\Error\Cloak;

$touch = new Cloak(
    touch(...),
    Cloak::THROW,
    E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED,
);

ReportingLevel类

因为有时处理PHP错误报告级别可能会令人困惑,该包提供了一种更友好的方法来处理它们。例如,前面的代码示例可以使用ReportingLevel类重写。

<?php
use Bakame\Aide\Error\Cloak;
use Bakame\Aide\Error\ReportingLevel;

$touch = new Cloak(
    touch(...),
    Cloak::THROW,
    ReportingLevel::fromExclusion(E_NOTICE, E_STRICT, E_DEPRECATED),
);

该类提供了一个更友好的API来简化对错误报告级别的操作

  • ReportingLevel::fromValue允许使用您想要的任何值实例化该类。
  • ReportingLevel::fromName允许使用与之一致的字符串实例化该类E_*常量。
  • ReportingLevel::fromEnv将类实例化为与当前环境设置匹配。
  • ReportingLevel::fromInclusion通过使用位OR操作将所有提交的值添加到从0开始的值中实例化错误级别,这意味着如果没有添加任何错误报告级别,则不存在错误报告级别。
  • ReportingLevel::fromExclusion执行相反的操作,每个给出的值都会从由E_ALL表示的最大值中减去。

除此之外,该类还提供了一个用于每个错误报告级别的构造,语法如下

use Bakame\Aide\Error\ReportingLevel;

ReportingLevel::warning()->value(); // returns the same value as E_WARNING.
ReportingLevel::userDeprecated()->value(); // returns the same value as E_USER_DEPRECATED.
// and so on for each error reporting level

您可以使用contains方法来判断正在配置哪种错误报告。该类还提供了excludedincluded方法,这两个方法返回错误报告级别的名称。

<?php

use Bakame\Aide\Error\ReportingLevel;

ReportingLevel::fromEnv()->contains(E_WARNING);
// returns true if the current value in error_reporting contains `E_WARNING`
// returns false otherwise.

$reportingLevel = ReportingLevel::fromInclusion(E_NOTICE, "E_DEPRECATED");
 
$reportingLevel->value();
// `value` returns the int value corresponding to the calculated error level.
//  the errorLevel calculated will ignore notice, and deprecated error.

$reportingLevel->excluded(); 
// returns all the error reporting level name no present in the current error Level

$reportingLevel->included(); 
// returns all the error reporting level name present in the current error Level
// ["E_NOTICE", "E_DEPRECATED"]

从Cloak实例访问错误报告级别

一旦实例化,您就可以始终通过Cloak实例上的errorLevel方法来访问错误报告级别。例如,如果您需要知道是否包含特定错误,可以执行以下操作

$touch = Cloak::all(touch(...));
$touch->reportingLevel()->contains(E_WARNING);  //tells if the E_WARNING is included or not

鸣谢