Skip to content

Exception Event

此組件會在 Hyperf 的異常處理器調度器處理異常後派發 ExceptionDispatched 事件,並提供輔助函數, 用於在不拋出異常的情況下手動報告異常。

安裝

shell
composer require friendsofhyperf/exception-event

組件的 ConfigProvider 會通過 Composer 包發現機制自動註冊切面。切面和監聽器依賴 Hyperf 的 AOP 及事件調度器支持,標準 Hyperf 應用已提供這些支持;在最小化安裝中,請確保 hyperf/dihyperf/event 可用。

自動派發

註冊的切面會攔截 Hyperf\ExceptionHandler\ExceptionHandlerDispatcher::dispatch()。調度器正常返回後, 組件會派發 ExceptionDispatched 事件,其中包含已處理的異常,以及上下文中的當前請求和響應。

定義監聽器

php
<?php

declare(strict_types=1);

namespace App\Listener;

use FriendsOfHyperf\ExceptionEvent\Event\ExceptionDispatched;
use Hyperf\Contract\StdoutLoggerInterface;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;

#[Listener]
class ExceptionEventListener implements ListenerInterface
{
    public function __construct(private StdoutLoggerInterface $logger)
    {
    }

    public function listen(): array
    {
        return [
            ExceptionDispatched::class,
        ];
    }

    /**
     * @param ExceptionDispatched $event
     */
    public function process(object $event): void
    {
        $exception = $event->throwable;

        $this->logger->error(sprintf(
            'Exception: %s in %s:%d',
            $exception->getMessage(),
            $exception->getFile(),
            $exception->getLine()
        ));
    }
}

事件屬性

FriendsOfHyperf\ExceptionEvent\Event\ExceptionDispatched 公開以下屬性:

  • Throwable $throwable:已處理或手動報告的異常。
  • ?ServerRequestInterface $request:當前請求;不在請求上下文中時為 null
  • ?ResponseInterface $response:當前響應;不在響應上下文中時為 null

手動報告

組件會自動加載三個命名空間輔助函數:

  • report(string|Throwable $exception = 'RuntimeException', ...$parameters):報告異常。
  • report_if($condition, string|Throwable $exception = 'RuntimeException', ...$parameters): 條件為真值時報告。
  • report_unless($condition, string|Throwable $exception = 'RuntimeException', ...$parameters): 條件為假值時報告。
php
use DomainException;

use function FriendsOfHyperf\ExceptionEvent\report;
use function FriendsOfHyperf\ExceptionEvent\report_if;
use function FriendsOfHyperf\ExceptionEvent\report_unless;

report(new DomainException('The operation failed.'));
report('The operation failed.'); // 使用此消息報告 RuntimeException。
report(DomainException::class, 'The operation failed.');

report_if($shouldReport, 'The operation failed.');
report_unless($operationSucceeded, 'The operation failed.');

report() 會直接派發 ExceptionDispatched,不會拋出異常。當第一個參數是已存在的異常類名時, 其餘參數會傳給該異常的構造函數;其他字符串會成為 RuntimeException 的消息。

report_if() 在條件為真值時報告,report_unless() 在條件為假值時報告。兩個函數都會返回原始條件。