亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

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 關注
  • 133 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號