为了账号安全,请及时绑定邮箱和手机立即绑定

PHP 不在类中抛出指定的错误消息

PHP 不在类中抛出指定的错误消息

PHP
富国沪深 2023-03-26 14:26:10
我有三个类,每个类在连接到我的数据库时处理不同的功能。具有处理连接名称的 1 类;带名称的类 2通过向用户 UI提供错误和成功消息,带名称的类 3使用 MySqli 连接从数据库中检索数据并将其传递给 UI。 这和我平时做数据库连接、收集和展示的方式不一样。通常我只是在三个文件中创建了很多函数,并在需要时调用它们。但是我的网站越来越大,越来越复杂,所以我正在重新组织一切。 我当前的问题是,当我在第 3 堂课中创建数据库连接时,它没有抛出我编写的错误。ConnectDB()MySqli()MessageOut()$_SESSION['message']WebApp()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);        }    }}我将我的 localhost 定义的密码更改为错误的密码并加载了文件,但是即使错误被抑制,错误也会在我的第一堂课的第 10 行给出。这个想法是在使用之前检查连接。我如何在我的第 3 堂课中得到抛出的错误,给我“数据库连接当前不可用”。信息?编辑所以我重新评估了我所做的并try-catch在constructor我的第三节课中设置了一个块,但我知道我得到了一个错误:Fatal error: Uncaught Error: Call to a member function prepare() on null in第 41 行的第三节课使用了数据库连接。
查看完整描述

1 回答

?
斯蒂芬大帝

TA贡献1827条经验 获得超8个赞

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


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


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


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


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


如果你仔细想想,你的课ConnectDB是很没用的。要连接到数据库,您始终需要相同的 3 行。mysqli 已经是一个类,所以在另一个类中包装 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.']);

}

我看到你已经命名了你的类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.

}

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


查看完整回答
反对 回复 2023-03-26
  • 1 回答
  • 0 关注
  • 108 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信