代码之家  ›  专栏  ›  技术社区  ›  user2834566

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

  •  0
  • user2834566  · 技术社区  · 5 年前

    我如何通过电子邮件将所有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帖子

    With PHP and mysqli, is it possible to catch all mysqli errors in one place across all PHP scripts?

    Good Way to Email Exceptions

    PHP exceptions error messages

    PHP exception inside catch: how to handle it?

    0 回复  |  直到 5 年前
        1
  •  0
  •   Your Common Sense    5 年前

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

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

    正如我在文章中所述 error reporting basics ,错误和异常是不同的野兽,每个都有自己的处理程序。因此,为了使错误处理统一,您必须首先将错误转换为异常,然后在异常处理程序中执行所需的处理,无论是日志记录、电子邮件还是其他任何方式。

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

    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抛出异常,这些异常将由上面定义的处理程序处理。

    推荐文章