簡體   English   中英

插入查詢中沒有真正的結果返回

[英]No true result return in insert query

這是我創建的用於查詢的類:

<?php
mysqli_report(MYSQLI_REPORT_INDEX | MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

class DBConnect {
    private $dbcon;
    private $paramquery;
    private $result;

    public function __construct() {
        try {
            $this->dbcon = mysqli_init();
            mysqli_real_connect($this->dbcon, '127.0.0.1', '', '', '', 3306, '', MYSQLI_CLIENT_COMPRESS);
            $this->paramquery = $this->dbcon->stmt_init();
        } catch (mysqli_sql_exception $e) {
            exit('Database Connection Failed');
        }
    }
    public function dbquery($querysql, $querydata) {
        try {
            mysqli_ping($this->dbcon);
            $this->paramquery->prepare($querysql);

            array_walk($querydata, function(&$escval){$escval = mysqli_real_escape_string($this->dbcon, $escval);});   //Problem
            call_user_func_array(array($this->paramquery, 'bind_param'), $querydata);   //Problem

            $this->paramquery->execute();
        } catch (mysqli_sql_exception $e) {
            exit('Database Query Failed');
        }

        $this->result = $this->paramquery->get_result();  // problem

        if ($this->result) {
            $drs = $this->result->fetch_array();
            $this->result->free_result();
            return $drs;
        }
    }
    public function __destruct() {
        if (($this->dbcon !== null) && ($this->paramquery !== null) && ($this->result !== null)) {
            $this->paramquery->close();
            $this->dbcon->close();
        }
        unset($this->result);
        unset($this->paramquery);
        unset($this->dbcon);
    }
}
?>

index.php 文件代碼是這樣的:

<?php

require_once('connection.php');

$DBX = new DBConnect();

$DBX->dbquery('INSERT INTO `xathx_key` (`license`, `client`, `server`, `uniquex`) VALUES (?, ?, ?, ?)', array('ssss', '1', '3', '5', '7'));

var_dump($DBX);
unset($DBX)
?>

我正在嘗試在這種情況下執行 INSERT 查詢。 並且我想在查詢成功執行時獲得成功結果或標志。 但是在對象的 var_dump 中我得到了一些不相關的數據,如果我使用 echo 我得到一個錯誤,該對象無法轉換為字符串。 我只想獲得 0 表示查詢執行失敗、損壞或問題,以及 1 表示完成、成功、正常狀態。 我什么時候在代碼中出錯了?

編輯:你們能告訴我這個簡單的腳本有什么問題嗎? 該腳本的主要目標是連接到 mysql 服務器並盡可能快地、盡可能安全地執行所有可能的查詢。

完整項目來源: https : //github.com/FSMySQL/PHP-FSMySQL

該腳本的主要目標是連接到mysql服務器,並盡可能安全地執行所有可能的查詢。

目標是一個很好的目標,但可以從許多改進中受益。

免責聲明:將有很多鏈接到我自己的網站,因為我在20多年的時間里一直在幫助使用PHP的人們,並且對撰寫有關最常見問題的文章很着迷。

錯誤報告的概念

首先,您需要更改錯誤報告的概念 您的exit()方法對於程序員來說將是一場噩夢 ,因為當出現問題時 ,錯誤消息是至關重要的信息源 程序員應不遺余力地嘗試獲取完整的錯誤消息。 在我的文章PHP錯誤報告中 ,我確實解釋了如何使錯誤報告既對程序員又對用戶友好。 簡而言之,您不應該當場捕獲錯誤,而應該在單個位置報告錯誤和異常,然后可以根據當前服務器的角色輕松進行配置。

盡管,正如另一個答案中所建議的那樣,您可以在index.php文件中使用全局try-catch塊充當此類全局錯誤處理程序,但我還是希望使用專用的錯誤處理程序腳本,如上面的文章中所述。 這將使您的代碼井井有條,並減少index.php的膨脹。

此外,您的“在插入查詢中返回真實結果”的想法與您使用異常的意圖相矛盾。 當使用異常時,沒有必要驗證立即函數的結果。 萬一發生錯誤,它只會冒泡到錯誤處理程序或catch塊,因此,它將永遠不會達到條件。 一個簡單的例子:

function test() {
    throw new Exception("Test");
    return false;
}
$result = test();
if ($result === false) {
    echo "false";
}

此示例中的代碼執行永遠不會達到條件 ,因此使您的函數在錯誤時返回false毫無用處。 反過來,這使得在成功時返回真實是多余的。 只是返回有意義的結果,但不要將其用作標志:只需編寫代碼而沒有任何條件,就好像一切都很好。 請記住,您在其他地方有錯誤處理代碼,如果發生錯誤,這些代碼將被神奇地調用。

連接

正如我在另一篇文章“ 如何使用mysqli正確連接”中所解釋的那樣,如果出現連接錯誤,則有少許機會顯示連接憑據。 為了避免發生這種情況,但要使程序員知道,我們必須拋出一個全新的異常 ,但是要保留錯誤信息-因此堆棧跟蹤將從throw行開始,因此不包含任何敏感信息。

而且,連接代碼缺少必要的部分- 設置正確的字符集 盡管在MySQL 8中默認設置了正確的字符集,但最好將其明確化。

同樣,使mysqli語句成為類變量也是一個嚴重的錯誤,它將導致競爭條件錯誤 您的類應保留的唯一狀態是與連接有關的狀態,但不能將單個類變量用於語句。

因此,讓我們根據以上文章中的代碼重寫您的構造函數:

public function __construct()
{
    mysqli_report(MYSQLI_REPORT_INDEX | MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
    try {
        $this->dbcon = mysqli_init();
        $this->dbcon->real_connect('127.0.0.1', '', '', '', 3306, '', MYSQLI_CLIENT_COMPRESS);
        $this->dbcon->set_charset('utf8mb4');
    } catch (\mysqli_sql_exception $e) {
        throw new \mysqli_sql_exception($e->getMessage(), $e->getCode());
    }
}

dbquery函數

坦率地說,該功能很奇怪。 准備好的語句和轉義之間是奇怪的混合。 讓我們根據我的mysqli helper函數重寫它,該函數實際上利用mysqli准備好的語句

public function dbquery($sql, $data = [], $types = "")
{
        $this->dbcon->ping(); // not sure if it's necessary 
        $stmt = $this->dbcon->prepare($sql);
        if ($data) {
            $types = $types ?: str_repeat("s", count($data));
            $stmt->bind_param($types, ...$data);
        }
        $stmt->execute();
        return $stmt->get_result();
}

現在,此功能可以滿足您對安全SQL查詢的需求

所以最后我們可以重寫您的index.php

<?php

require_once('connection.php');
$DBX = new DBConnect();

$sql = 'INSERT INTO `xathx_key` (`license`, `client`, `server`, `uniquex`) VALUES (?, ?, ?, ?)';
$DBX->dbquery($sql, ['1', '3', '5', '7']);

就像您在上面學到的那樣,不需要“成功執行查詢時的標志”。 就像總能成功一樣。 如果出現錯誤,它將無條件顯示(如果在索引中包含錯誤處理程序腳本,則將正確處理實時站點上的錯誤)。

你有一個問題

$this->result = $this->paramquery->get_result();

因為mysqli_stmt::get_result returns a resultset for successful SELECT queries, or FALSE for other DML queries or on failure.

Other DML-queries是INSERT,UPDATE,DELETE。 這就是示例中的內容。

要解決您的問題,您可以通過向$mysqli->errno添加一些額外的檢查來修改類:

$this->result = $this->paramquery->get_result();
if ($this->result) {
    ...
}

if ($this->paramquery->errno !== 0) { // we have some real error
    exit('Database Query Failed');
}

// we have DML-query (INSERT, UPDATE, DELETE)
// and we can return number of affected rows (if it's necessary)
return $this->paramquery->affected_rows;

PS:我同意這一評論 ,我認為您的課程僅應用於教育目的,因為它有多個嚴重缺陷。

在您的DBConnect類中,您有try catch塊。 但是您的catch塊只是使用exit語句終止了請求。 您的班級不應這樣做。

假設您將其部署在生產環境中,並且由於某種原因數據庫連接失敗。 在這種情況下,用戶將僅看到帶有“數據庫連接失敗”消息的白色屏幕,這看起來一點也不專業。

相反,您的類應該將此信息傳遞回index.php ,后者調用了該類的方法,並讓index.php處理錯誤消息或異常。

因此,我將對您的代碼進行以下更改:

  1. DBConnect類應該拋出一個異常,而不是完全終止程序的執行。 下面是__contruct()外觀。
    public function __construct() {
        try {
            $this->dbcon = mysqli_init();
            mysqli_real_connect($this->dbcon, '127.0.0.1', '', '', '', 3306, '', MYSQLI_CLIENT_COMPRESS);
            $this->paramquery = $this->dbcon->stmt_init();
        } catch (mysqli_sql_exception $e) {
            //exit('Database Connection Failed'); Commented this out.
            //Throw the Exception Here. This will then be passed to the calling code.
            throw $e;
        }
    }

您將需要相應地更改其他方法。

  1. index.php文件中,您應該尋找上述異常。 因此,您應該將代碼移到“嘗試捕獲”塊中以捕獲該異常。
require_once('connection.php');

try {
    $DBX = new DBConnect();
    $DBX->dbquery('INSERT INTO `xathx_key` (`license`, `client`, `server`, `uniquex`) VALUES (?, ?, ?, ?)', array('ssss', '1', '3', '5', '7'));
} catch (Exception $e) {
    $message =  'Caught exception: ',  $e->getMessage() . "\n";
    //Display this Message to User in an appropriate way.
    //Write to Error Log
}

//var_dump($DBX);
//unset($DBX) 

因此,這將在數據庫連接失敗以及插入查詢失敗時捕獲到異常。 您可以將異常寫入日志,以便以后檢查它們,並可以根據引起的異常向用戶顯示任何適當的錯誤消息。

您可以在PHP手冊中閱讀有關異常的更多信息

我認為您正在尋找: return true; return 1; 成功插入記錄或查詢后。

            $this->db->update('table_name',$Array_to_insert);                 
            $last_id = $this->db->insert_id();
            if($this->db->affected_rows() == 1){ 
              return TRUE;
            }
            else { 
              return FALSE;
            }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM