繁体   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