插入查询中没有真正的结果返回

这是我创建的用于查询的类:


<?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);

    }

}

?>


我正在尝试在这种情况下执行 INSERT 查询。并且我想在查询成功执行时获得成功结果或标志。但是在对象的 var_dump 中我得到了一些不相关的数据,如果我使用 echo 我得到一个错误,该对象无法转换为字符串。我只想获得 0 表示查询执行失败、损坏或问题,以及 1 表示完成、成功、正常状态。我什么时候在代码中出错了?


编辑:你们能告诉我这个简单的脚本有什么问题吗?此脚本的主要目标是连接到 mysql 服务器并尽可能快地、尽可能安全地执行所有可能的查询。


完整项目来源:https : //github.com/FSMySQL/PHP-FSMySQL


烙印99
浏览 194回答 3
3回答

噜噜哒

此脚本的主要目标是连接到 mysql 服务器并尽可能快地、尽可能安全地执行所有可能的查询。目标很好,但实施可以从许多改进中受益。免责声明:会有很多指向我自己网站的链接,因为我帮助人们使用 PHP 20 多年,并且痴迷于撰写有关最常见问题的文章。错误报告的概念首先,你需要改变错误报告的概念。您的exit()方法对程序员来说将是一场噩梦,因为错误消息是出现问题时的重要信息来源。程序员应该不遗余力地尝试获取完整的错误消息。在我的文章PHP 错误报告中,我确实解释了如何使错误报告对程序员和用户友好。简而言之,你不应该当场捕获错误,而是有一个专门的地方来报告错误和异常,然后可以根据当前服务器的角色轻松配置它。虽然,正如其他答案中所建议的,您可以在 index.php 文件中使用全局 try-catch 块来充当这样的全局错误处理程序,但我更喜欢专用的错误处理程序脚本,如上面的文章中所述。它会让你的代码更有条理,让 index.php 不那么臃肿。此外,您认为“在插入查询中返回真实结果”的想法与您使用异常的意图相矛盾。当使用异常时,没有必要验证立即函数的结果。如果出现错误,它只会冒泡到错误处理程序或 catch 块,因此,它永远不会达到条件。一个简单的例子:function test() {&nbsp; &nbsp; throw new Exception("Test");&nbsp; &nbsp; return false;}$result = test();if ($result === false) {&nbsp; &nbsp; echo "false";}此示例中的代码执行永远不会达到条件,因此使您的函数在出错时返回 false 无用。反过来,这使得在成功时返回 true 是多余的。只需返回一个有意义的结果,但不要将其用作标志:只需编写没有任何条件的代码,就好像一切都很好。请记住,您在其他地方拥有错误处理代码,这些代码将在发生错误时神奇地调用。联系正如我在另一篇文章如何使用 mysqli 正确连接中所解释的那样,在连接错误的情况下,有一点机会显示连接凭据。为了避免任何可能性但让程序员知道我们必须抛出一个全新的异常,但保留错误信息 - 因此堆栈跟踪将从抛出行开始,因此不包含敏感信息。此外,连接代码缺少一个必不可少的部分 -设置正确的字符集。尽管在 MySQL 8 中默认设置了正确的字符集,但最好使其明确。此外,将 mysqli 语句作为类变量是一个严重的错误,会导致竞争条件错误。您的类应该保留的唯一状态是与连接相关的状态,但不应将单个类变量用于语句。因此,让我们根据上面文章中的代码重写您的构造函数:public function __construct(){&nbsp; &nbsp; mysqli_report(MYSQLI_REPORT_INDEX | MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);&nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; $this->dbcon = mysqli_init();&nbsp; &nbsp; &nbsp; &nbsp; $this->dbcon->real_connect('127.0.0.1', '', '', '', 3306, '', MYSQLI_CLIENT_COMPRESS);&nbsp; &nbsp; &nbsp; &nbsp; $this->dbcon->set_charset('utf8mb4');&nbsp; &nbsp; } catch (\mysqli_sql_exception $e) {&nbsp; &nbsp; &nbsp; &nbsp; throw new \mysqli_sql_exception($e->getMessage(), $e->getCode());&nbsp; &nbsp; }}dbquery 函数坦率地说,这个功能很奇怪。这是准备好的语句和转义之间的奇怪组合。让我们根据我的mysqli helper 函数重写它,该函数实际上使用了 mysqli 准备好的语句public function dbquery($sql, $data = [], $types = ""){&nbsp; &nbsp; &nbsp; &nbsp; $this->dbcon->ping(); // not sure if it's necessary&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; $stmt = $this->dbcon->prepare($sql);&nbsp; &nbsp; &nbsp; &nbsp; if ($data) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $types = $types ?: str_repeat("s", count($data));&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $stmt->bind_param($types, ...$data);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; $stmt->execute();&nbsp; &nbsp; &nbsp; &nbsp; return $stmt->get_result();}现在这个函数满足了你对安全 SQL 查询的渴望所以最后我们可以重写你的 index.php<?phprequire_once('connection.php');$DBX = new DBConnect();$sql = 'INSERT INTO `xathx_key` (`license`, `client`, `server`, `uniquex`) VALUES (?, ?, ?, ?)';$DBX->dbquery($sql, ['1', '3', '5', '7']);正如您在上面了解到的,不需要“成功执行查询时的标志”。就好像总是成功一样。如果出现错误,它将在没有任何条件的情况下出现(如果您在索引中包含错误处理程序脚本,则会正确处理实时站点上的错误)。

慕姐8265434

你有问题$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是插入、更新、删除。这正是您在示例中所拥有的。要解决您的问题,您可以通过添加一些额外的检查来修改类$mysqli->errno:$this->result = $this->paramquery->get_result();if ($this->result) {&nbsp; &nbsp; ...}if ($this->paramquery->errno !== 0) { // we have some real error&nbsp; &nbsp; 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处理错误消息或异常的类。因此,我将对您的代码进行以下更改:DBConnect类应该抛出异常而不是完全终止程序的执行。下面是__contruct()应该的样子。&nbsp; &nbsp; public function __construct() {&nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $this->dbcon = mysqli_init();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mysqli_real_connect($this->dbcon, '127.0.0.1', '', '', '', 3306, '', MYSQLI_CLIENT_COMPRESS);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $this->paramquery = $this->dbcon->stmt_init();&nbsp; &nbsp; &nbsp; &nbsp; } catch (mysqli_sql_exception $e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //exit('Database Connection Failed'); Commented this out.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //Throw the Exception Here. This will then be passed to the calling code.&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw $e;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }您将需要相应地更改其他方法。在您的index.php文件中,您应该寻找捕获上述异常。因此,您应该将代码移到 Try Catch 块中以捕获该异常。require_once('connection.php');try {&nbsp; &nbsp; $DBX = new DBConnect();&nbsp; &nbsp; $DBX->dbquery('INSERT INTO `xathx_key` (`license`, `client`, `server`, `uniquex`) VALUES (?, ?, ?, ?)', array('ssss', '1', '3', '5', '7'));} catch (Exception $e) {&nbsp; &nbsp; $message =&nbsp; 'Caught exception: ',&nbsp; $e->getMessage() . "\n";&nbsp; &nbsp; //Display this Message to User in an appropriate way.&nbsp; &nbsp; //Write to Error Log}//var_dump($DBX);//unset($DBX)&nbsp;因此,如果数据库连接失败以及插入查询失败,这将捕获异常。您可以将异常写入日志,以便稍后检查它们,并且您可以根据导致的异常向用户显示任何适当的错误消息。您可以在PHP 手册中阅读有关异常的更多信息
打开App,查看更多内容
随时随地看视频慕课网APP