繁体   English   中英

PHP 未在 Class 中抛出指定的错误消息

[英]PHP not throwing specified error message in Class

我有三个类,每个类在连接到我的数据库时处理不同的功能。
Class 1,名称为ConnectDB() ,用于处理MySqli()连接; Class 2 名称为MessageOut() ,它通过$_SESSION['message']键向用户 UI 提供错误和成功消息,Class 3 名称为WebApp()使用 MySqli 连接从数据库中检索数据并将其传递给用户界面。

这和我平时做数据库连接、收集和展示的方式不一样。 通常我只是在三个文件中创建了很多函数,并在需要时调用它们。 但是我的网站越来越大,越来越复杂,所以我正在重新组织一切。
我当前的问题是当我在我的第 3 个 class 中创建数据库连接时,它没有抛出我编程的错误。

class ConnectDB {
    //Connecting to database
    public function connect() {
        //connecting to mysql
        @$conn = new mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
        // check validity of database connection
        if (mysqli_connect_errno()) {
            return false;
            exit();
        }
        // select the database to use
        return $conn;
    }
}

ini_set('display_errors', 1); 
    ini_set('log_errors',1); 
    error_reporting(E_ALL); 
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
class WebApp {
    protected $db;
    function __construct(){
        $this->connector = new ConnectDB();
        $this->messager = new MessageOut();
        try {
            $this->db = $this->connector->connect();
            if(!$this->db) {
                throw new Exception(' Database connection is currently unavailable.');
            }
        } catch (Exception $e) {
            mysqli_report(MYSQLI_REPORT_OFF);
            $errors = array();
            $message = $e->getMessage();
            //populate array with message and divert output to error class functions
            array_push($errors, $message);
            $this->messager->erroutput($errors);
        }
    }
    public function selectIdata() {
        //select data
        try {
            $query = "SELECT *
                        FROM thetable";
            $stmt = $this->db->prepare($query);
            $stmt->execute();
            $stmt->store_result();

            $stmt->bind_result($idata);
            $result = [];
            if ($stmt->num_rows > 0) {
                while ($stmt->fetch()) {
                    $result[] = $idata;
                }
                return $result;
            } else {
                return false;
            }
        } catch (Exception $e) {
            mysqli_report(MYSQLI_REPORT_OFF);
            $errors = array();
            $message = $e->getMessage();
            //populate array with message and divert output to error class functions
            array_push($errors, $message);
            $this->messager->erroutput($errors);
        }
    }
}

我将我的 localhost 定义的密码更改为错误的密码并加载了文件,但错误在我的第一个 class 中的第 10 行给出,即使错误被抑制。 这个想法是在使用之前检查连接。
我如何在我的第 3 个 class 中得到抛出的错误,给我“数据库连接当前不可用”。 信息?

编辑
所以我重新评估了我所做的事情,并在我的第三个 class 的constructor中设置了一个try-catch块,但我知道我收到一个错误: Fatal error: Uncaught Error: Call to a member function prepare() on null in the 3rd 88398112 on line195188 41 使用数据库连接。

看来您误解了错误报告的概念。 我将尝试向您阐明一般概念。

错误报告是为了通知开发人员错误的编码、错误和其他需要修复的潜在问题。 错误报告不适用于该产品的用户。 在开发过程中,您可以自己启用display_errors ,但绝不能将其留在代码中。 但是,您应该始终记录错误。 PHP 有一个非常好的错误记录器,但我可以理解它对您来说可能不够用,并且您想记录更多信息和错误消息。

您可以编写通用错误处理程序并捕获应用程序抛出的所有错误和异常,并使用您自己的记录器软件将其记录到服务器上的安全位置。 不要在代码中间捕获异常。 这样的记录器需要是您的应用程序的核心,并且在一个单独的文件中,以便能够捕获所有错误。

出于这个原因,您的 try-catch 不是很有用,因为您将它放在多个地方并且它与您的应用程序代码交织在一起。 此外,您只捕获异常并忽略错误。 你应该抓住两者。 使用诸如catch(\Throwable $e)类的东西来捕获两者。

@是错误抑制运算符。 应该不惜一切代价避免它。 如果你不能避免它,那么你需要重写代码来避免它。 您在 mysqli 连接上所做的实际上是忽略了错误两次。 首先,您使用@然后终止您的脚本。 不要杀死脚本。 不要沉默错误。 让你的错误冒出来,让它们被你的错误处理程序捕获。

如果您考虑一下,您的 class ConnectDB是非常无用的。 要连接到数据库,您始终需要相同的 3 行。 mysqli 已经是一个 class 所以在另一个 class 中包装 3 行是没有意义的。 正确的代码应该无外乎:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$conn = new mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
$conn->set_charset('utf8mb4');

当 mysqli 无法连接时,您当前的脚本会退出,但即使您没有消除错误并且打开了错误报告,变量也不可能为空。 if(!$this->db)成为另一个谬误。 此外,当您刚刚将一个异常静音时,为什么要抛出异常? 这让我想到了另一点。 为什么在立即捕获时抛出异常? 当然,整个逻辑无非就是一个简单的 if 语句:

if(!$this->db) {
    $this->messager->erroutput([' Database connection is currently unavailable.']);
}

我看到您已将您的 class MessageOut命名为 MessageOut,我真的希望您不要将错误消息暴露给用户。 这不仅是糟糕的用户体验,而且还有安全风险。 您应该改为实现一个漂亮的 HTTP 500 错误页面,或者如果您的应用程序足够复杂,您自己的错误页面将在您的错误处理程序捕获错误时显示。

一旦发现错误就关闭 mysqli 错误报告没有任何意义。 只需删除mysqli_report(MYSQLI_REPORT_OFF); 从你的代码。

要形象化我所描述的内容,请考虑以下代码:

<?php

// ini_set('display_errors', 1);
ini_set('log_errors', 1);
error_reporting(E_ALL);

class WebApp {
    protected $db;

    function __construct() {
        $this->messager = new MessageOut();

        mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); // it can also be at the top of the script, but it makes more sense to put it together with the rest of mysqli code
        $this->db = new \mysqli(DB_HOST, DB_USERRW, DB_PASSWRW, DB_DBASE);
        $this->db->set_charset('utf8mb4');
    }

    public function selectIdata() {
        //select data
        $query = "SELECT *
                    FROM thetable";
        $stmt = $this->db->prepare($query);
        $stmt->execute();
        $stmt->store_result();

        $stmt->bind_result($idata);
        $result = [];
        while ($stmt->fetch()) {
            $result[] = $idata;
        }
        return $result;
    }
}

try {
    $app = new \WebApp();
} catch (\Throwable $e) {
    // log your errors here.
}

它不是完美的代码,因为错误处理程序不在那里,它也应该在一个单独的文件中,但总体思路是避免应用程序逻辑中不必要的代码。 不要 try-catch。不要消除错误,也不要添加无用的代码。 把事情简单化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM