首页 > 解决方案 > 如何通过电子邮件发送所有 PHP 异常/错误的详细信息,包括 mysqli 的?

问题描述

如何获取所有 PHP 异常,包括由 mysqli 生成的和普通的 php 异常通过电子邮件发送给我?

问题环境

我在我的 ISP 处使用共享服务器,并且无权访问任何管理员类型的 PHP 配置文件。在服务器上,我只有大约一百行 PHP 对 MySQL 数据库执行查询,如果返回任何行,它会执行一些 SQL UPDATE 命令。这是每天作为 cron 作业运行的。没有关联的网站(我什至在该服务器上都没有网站)。服务器托管一个用于远程连接的数据库,而 php 只是对其进行一些维护。

由于没有“用户”和“网页”可以提供反馈,我希望所有错误和异常都通过电子邮件发送给我。

我尝试过/研究过的事情

我发现

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

会将通常只会导致返回 FALSE 的 mysqli 错误转换为将写入错误日志的异常。这有帮助。

...我可以使用例如电子邮件发送文本

$email = "my message";
Error_log($email, 1, "myemailaddress@myserver.com", "From: defaultemail@hostingserver.com");  

并且我可以通过编写自己的错误处理程序来获取错误的详细信息,例如

function the_error_handler($number, $message, $file, $line, $vars) //putting $vars in shows all the variables the server knows about
{
    $email = " An error ($number) occurred on line $line in $file.  $message ";
    Error_log($email, 1, "myemailaddress@myserver.com", "From: defaultemail@hostingserver.com");

    };

并使用

set_error_handler('the_error_handler'); 

最小的,可重现的例子

在下面的代码中,我将所有这些放在一起并故意引入了两个错误(尝试回显一个不存在的变量并尝试对一个不存在的表执行查询。

<?php

function the_error_handler($number, $message, $file, $line, $vars) //putting $vars in shows all the variables the server knows about(inluding passwords)
{
    $email = " An error ($number) occurred on line $line in $file.  $message ";
    Error_log($email, 1, "myemailaddress@myserver.com", "From: defaultemail@hostingserver.com");
};

set_error_handler('the_error_handler');

echo $NonExsitentVariable;  //<--deliberate error

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

$servername = "65.78.165.199";
$username = "test_user"; //execute, select, update and create temp files rights
$password = "U7frgh%^yT";
$dbname = "devlopment_db";

$the_sql = "SELECT  * FROM non_existent_table;";   //<-- another deliberate error
$conn    = mysqli_connect($servername, $username, $password, $dbname); // Create connection
$result  = mysqli_query($conn, $the_sql); //run the query and get a pointer to the result
$rows    = mysqli_fetch_all($result, MYSQLI_ASSOC); //convert to an associative array of rows to send back 
?>

结果

结果是不存在的变量错误会通过电子邮件发送给我,但 mysqli 错误只是被放入服务器上的错误日志中,而不是通过电子邮件发送。

如何通过电子邮件将这两个或所有错误发送给我?(显然,真正的代码有点复杂,如果在这里完整发布会混淆问题,但如果我能理解如何处理这个更简单的例子,原理是一样的)

背景

我从事计算机编程和讲授大约 35 年,直到不久前退休,但从来没有需要(或希望!)用 PHP 编程。这是我的第一个脚本之一,可能是我的最后一个脚本,所以如果你能提供帮助,请合理明确地说明我需要做什么,因为我不太熟悉 PHP 语法或编程环境)

我看过的一些SO帖子

使用 PHP 和 mysqli,是否可以在所有 PHP 脚本中在一个地方捕获所有 mysqli 错误?

发送电子邮件异常的好方法

PHP 异常错误信息

catch 中的 PHP 异常:如何处理?

标签: phpemailexceptionmysqli

解决方案


首先,我必须警告您,在一个向公众开放的实时站点上,当对站点的每个请求都会导致发送不同的电子邮件时,如果出现某些严重故障,电子邮件错误可能会淹没您的邮箱。我工作的公司不止一次发生这种情况。有时很难在错误的瀑布中找到真正的原因。

监控服务器日志被认为是更安全和准确的解决方案。在我看来,在错误日志上使用 Grep 比浏览电子邮件更有效。但无论哪种方式,这里的问题是如何统一处理所有错误,而在处理程序中采取的操作可以是任何东西。

所以就像我在关于错误报告基础的文章中展示的那样,错误和异常是不同的野兽,每个都有自己的处理程序。因此,要使错误处理统一,您必须首先将错误转换为异常,然后在异常处理程序中进行所需的处理,无论它是什么 - 日志记录、电子邮件或任何东西。

因此,您将需要本文中介绍的两个函数,一个简单地将错误转换为异常的错误处理程序,

set_error_handler(function ($level, $message, $file = '', $line = 0)
{
    throw new ErrorException($message, 0, $level, $file, $line);
});

和这样的异常处理程序

set_exception_handler(function ($e)
{
    error_log($e);
    http_response_code(500);
    if (ini_get('display_errors')) {
        echo $e;
    } else {
        error_log($e, 1, "myemailaddress@myserver.com", "From: defaultemail@hostingserver.com");
        echo "<h1>500 Internal Server Error</h1>
              An internal server error has been occurred.<br>
              Please try again later.";
    }
});

每次发生错误并且代码在实时站点上运行时,都会向您发送一封电子邮件。

此外,您可能希望添加一个致命错误处理程序,它可能有助于处理同名错误。可以在文章中看到所有三个处理程序组合在一起的完整示例。

关于mysqli,你是绝对正确的,下面这行

 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

将告诉 mysqli 抛出异常,这些异常将由上面定义的处理程序处理。


推荐阅读