samsonasik/error-hero-module

用于捕获 Laminas 和 Mezzio 应用程序中 PHP 错误和异常的英雄

5.1.0 2023-05-28 15:52 UTC

README

Latest Version ci build Code Coverage PHPStan Downloads

这是版本 ^5.0 的 README,它仅支持 Laminas Mvc 版本 3 和 Mezzio 版本 3,以及 php ^8.1。

对于版本 ^4.0,您可以阅读版本 4 的 README,它仅支持 Laminas Mvc 版本 3 和 Mezzio 版本 3,以及 php ^8.0。

简介

ErrorHeroModule 是一个模块,用于记录 Laminas Mvc 3 应用程序的错误(数据库和邮件)以及 Mezzio 3 中的异常,在 'dispatch.error' 或 'render.error' 或请求和响应期间,以及 PHP E_* 错误

特性

  • 使用 Db Writer Adapter 保存到数据库。
  • 在所有事件过程中记录异常(dispatch.error 和 render.error)和 PHP 错误。
  • 支持在配置设置中排除 PHP E_* 错误(例如:排除 E_USER_DEPRECATED 或具有特定消息的特定 E_USER_DEPRECATED)。
  • 支持在配置设置中排除 PHP 异常(例如:异常类或继承它的类或具有特定消息的特定异常类)。
  • 在配置的时间范围内,对同一错误仅记录一次日志。
  • 如果配置了 'display_errors' = 0,则为错误设置默认页面(Web 访问)或默认消息(控制台访问)。
  • 通过 'ajax' 配置设置请求是 XMLHttpRequest 时的默认内容。
  • 通过 'no_template' 配置设置没有模板服务时的默认内容(Mezzio 3)。
  • 提供请求信息(http 方法、原始数据、正文数据、查询数据、文件数据、cookie 数据和 IP 地址)。
  • 发送邮件
    • 将多个收件人列入配置的电子邮件中
    • 在上传错误时将 $_FILES 包含在附件中(可配置是否包含)。

安装

1. 导入以下 SQL 语句用于 Mysql

DROP TABLE IF EXISTS `log`;

CREATE TABLE `log` (
  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `type` int(11) NOT NULL,
  `event` text NOT NULL,
  `url` varchar(2000) NOT NULL,
  `file` varchar(2000) NOT NULL,
  `line` int(11) NOT NULL,
  `error_type` varchar(255) NOT NULL,
  `trace` text NULL,
  `request_data` text NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

如果您使用其他 RDBMS,您可以遵循上面的 log 表结构。

2. 设置您的 Laminas\Db\Adapter\AdapterInterface 服务或您的 Doctrine\ORM\EntityManager 服务配置

您可以使用 'db'(带有 Laminas\Db)配置或 'doctrine'(带有 DoctrineORMModule)配置,这将转换为与 Laminas\Log\Writer\Db 一起使用。

<?php
// config/autoload/local.php
return [
    'db' => [
        'username' => 'mysqluser',
        'password' => 'mysqlpassword',
        'driver'   => 'pdo_mysql',
        'database' => 'mysqldbname',
        'host'     => 'mysqlhost',
        'driver_options' => [
            \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
        ],
    ],
];

或者

<?php
// config/autoload/local.php
return [
    'doctrine' => [
        'connection' => [
            'orm_default' => [
                'driverClass' => 'Doctrine\DBAL\Driver\PDO\MySql\Driver',
                'params' => [
                    'user'     => 'mysqluser',
                    'password' => 'mysqlpassword',
                    'dbname'   => 'mysqldbname',
                    'host'     => 'mysqlhost',
                    'port'     => '3306',
                    'driverOptions' => [
                        \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\'',
                    ],
                ],
            ],
        ],
    ]
];

如果您使用其他 RDBMS,您可能需要配置您自己的 dbdoctrine 配置。

3. 需要此模块使用 composer

composer require samsonasik/error-hero-module

4. 复制配置

a. 对于 Laminas Mvc 应用程序,将 error-hero-module.local.php.dist 配置复制到您本地的 autoload 并进行配置

或运行复制命令

cp vendor/samsonasik/error-hero-module/config/error-hero-module.local.php.dist config/autoload/error-hero-module.local.php

b. 对于 Mezzio 应用程序,将 mezzio-error-hero-module.local.php.dist 配置复制到您本地的 autoload 并进行配置

或运行复制命令

cp vendor/samsonasik/error-hero-module/config/mezzio-error-hero-module.local.php.dist config/autoload/mezzio-error-hero-module.local.php

完成时,您可以修改名为 ErrorHeroModuleLoggererror-hero-module 的日志服务以及您本地的配置中的配置。

<?php
// config/autoload/error-hero-module.local.php or config/autoload/mezzio-error-hero-module.local.php

use Laminas\Db\Adapter\AdapterInterface;

return [

    'log' => [
        'ErrorHeroModuleLogger' => [
            'writers' => [

                [
                    'name' => 'db',
                    'options' => [
                        'db'     => AdapterInterface::class,
                        'table'  => 'log',
                        'column' => [
                            'timestamp' => 'date',
                            'priority'  => 'type',
                            'message'   => 'event',
                            'extra'     => [
                                'url'          => 'url',
                                'file'         => 'file',
                                'line'         => 'line',
                                'error_type'   => 'error_type',
                                'trace'        => 'trace',
                                'request_data' => 'request_data'
                            ],
                        ],
                        'formatter' => [
                            'name' => 'db',
                            'options' => [
                                'dateTimeFormat' => 'Y-m-d H:i:s',
                            ],
                        ],
                    ],
                ],

            ],
        ],
    ],

    'error-hero-module' => [
	// it's for the enable/disable the logger functionality
        'enable' => true,

        // default to true, if set to true, then you can see sample:
        // 1. /error-preview page ( ErrorHeroModule\Controller\ErrorPreviewController )
        // 2. errorheromodule:preview command ( ErrorHeroModule\Command\Preview\ErrorPreviewConsoleCommand ) via
        //       php public/index.php error-preview
        //
        // for Mezzio ^3.0.0, the disable error-preview page is by unregister 'error-preview' from config/routes
        //
        //
        // otherwise(false), you can't see them, eg: on production env.
        'enable-error-preview-page' => true,

        'display-settings' => [

            // excluded php errors ( https://php.ac.cn/manual/en/errorfunc.constants.php )
            'exclude-php-errors' => [

                // can be specific error
                \E_USER_DEPRECATED,

                // can be specific error with specific message
                [\E_WARNING, 'specific error message'],

            ],

            // excluded exceptions
            'exclude-exceptions' => [

                // can be an Exception class or class extends Exception class
                \App\Exception\MyException::class,

                // can be specific exception with specific message
                [\RuntimeException::class, 'specific exception message'],

                // or specific Error class with specific message
                [\Error::class, 'specific error message'],

            ],

            // show or not error
            'display_errors'  => 0,

            // if enable and display_errors = 0, the page will bring layout and view
            'template' => [
                // non laminas-view (plates, twig) for Mezzio not need a layout definition
                // as layout defined in the view
                'layout' => 'layout/layout',
                'view'   => 'error-hero-module/error-default'
            ],

            // for Mezzio, when container doesn't has \Mezzio\Template\TemplateRendererInterface service
            // if enable, and display_errors = 0, then show a message under no_template config
            'no_template' => [
                'message' => <<<json
{
    "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html",
    "title": "Internal Server Error",
    "status": 500,
    "detail": "We have encountered a problem and we can not fulfill your request. An error report has been generated and sent to the support team and someone will attend to this problem urgently. Please try again later. Thank you for your patience."
}
json
            ],

            // if enable and display_errors = 0, the console will bring message for laminas-mvc
            'console' => [
                'message' => 'We have encountered a problem and we can not fulfill your request. An error report has been generated and sent to the support team and someone will attend to this problem urgently. Please try again later. Thank you for your patience.',
            ],
            // if enable, display_errors = 0, and request XMLHttpRequest
            // on this case, the "template" key will be ignored.
            'ajax' => [
                'message' => <<<json
{
    "type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html",
    "title": "Internal Server Error",
    "status": 500,
    "detail": "We have encountered a problem and we can not fulfill your request. An error report has been generated and sent to the support team and someone will attend to this problem urgently. Please try again later. Thank you for your patience."
}
json
            ],
        ],

        'logging-settings' => [
            // time range for same error, file, line, url, message to be re-logged
	        // in seconds range, 86400 means 1 day
            'same-error-log-time-range' => 86400,
        ],

        'email-notification-settings' => [
            // set to true to activate email notification on log error event
            'enable' => false,

            // Laminas\Mail\Message instance registered at service manager
            'mail-message'   => 'YourMailMessageService',

            // Laminas\Mail\Transport\TransportInterface instance registered at service manager
            'mail-transport' => 'YourMailTransportService',

            // email sender
            'email-from'    => 'Sender Name <sender@host.com>',

            // to include or not $_FILES on send mail
            'include-files-to-attachments' => true,

            'email-to-send' => [
                'developer1@foo.com',
                'developer2@foo.com',
            ],
        ],
    ],
    // ...
];

5. 最后,启用它

针对 Laminas Mvc 应用

// config/modules.config.php or config/application.config.php
return [
    'Application',
    'ErrorHeroModule', // <-- register here
],

针对 Mezzio 应用

对于 laminas-mezzio-skeleton ^3.0.0,您需要打开 config/pipeline.php 并在默认 ErrorHandler::class 注册后添加 ErrorHeroModule\Middleware\Mezzio::class 中间件

$app->pipe(ErrorHandler::class);
$app->pipe(ErrorHeroModule\Middleware\Mezzio::class); // here

并在 config/routes.php 中添加 error-preview 路由(可选)

// for use laminas-router
$app->get('/error-preview[/:action]', ErrorHeroModule\Middleware\Routed\Preview\ErrorPreviewAction::class, 'error-preview');

// for use FastRoute
$app->get('/error-preview[/{action}]', ErrorHeroModule\Middleware\Routed\Preview\ErrorPreviewAction::class, 'error-preview');

以启用错误预览页面。要禁用错误预览页面,只需从路由中删除它。

试试看吧!

网络访问

如果 display_errors 配置为 0,您将看到以下页面

error preview in web

控制台访问

您可以在 laminas-cli 中使用此模块,您可以安装

composer require laminas/laminas-cli --sort-packages

然后您可以看到错误预览控制台

如果 display_errors 配置为 0,您将看到以下页面

error preview in console

您可以通过扩展 BaseLoggingCommand 在控制台应用程序中使用错误处理,如下所示

namespace Application\Command;

use ErrorHeroModule\Command\BaseLoggingCommand;
use Exception;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;

final class HelloWorld extends BaseLoggingCommand
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        throw new Exception('some exception logged to DB');
    }
}

并注册到您的服务中,如文档中所述。

对于生产环境,您可以通过将 ['error-hero-module']['enable-error-preview-page'] 设置为 false 来禁用错误预览示例页面。

贡献

欢迎贡献。请阅读 CONTRIBUTING.md