【问题标题】:Fatal error: Uncaught TypeError: Return value of safeQuery() must be of the type array or null, bool returned致命错误:未捕获的TypeError:safeQuery()的返回值必须是数组或null类型,返回bool
【发布时间】:2020-07-08 23:03:48
【问题描述】:

我遇到了一个问题。我收到此错误

致命错误:未捕获的 TypeError:safeQuery() 的返回值必须是数组类型或 null,在 E:\Hosted\action\conn\dbc.php:69 中返回的 bool 堆栈跟踪:#0 E:\Hosted \action\conn\dbc.php(6): safeQuery('INSERT INTO cu...', Array) #1 {main} 在第 69 行的 E:\Hosted\action\conn\dbc.php 中抛出

我不确定我的错误在哪里。代码正在运行。但突然它停止了。我可能犯了一个错误。 我的疑问是对的。我已经对此进行了双重检查。 这是我的代码:

<?php
// Test:
    $sql = "INSERT INTO `customers`(`name`, `email`, `phn_num`) VALUES (?, ?, ?)";
    $params = array("Assad Rajab", "email@gmail.com", "0123456789");
    $cus_id = safeQuery($sql, $params);
    

function safeQuery(string $sql, array $params = [], $db = NULL ): ?array {
    mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

    $conn = mysqli_connect("localhost", "phpmyadminuser", "Technik-Phone-Admin");
    if (!$conn) {
        die("no connection to database");
    } else {
        if (!mysqli_set_charset($conn, "utf8")) {
            die("Error loading character set utf8: </br>". mysqli_error($conn));
        } else {
            if (isset($db)) {
                // Use the given DB 
                mysqli_select_db($conn, $db);
            } else {
                // Use the default DB
                mysqli_select_db($conn, "technik-phone_mng");
            }
        }
    }

    // Prepare statement:
    $stmt = mysqli_prepare($conn, $sql);
    // If the statement has parameters then bind them all now
    if ($params) {
        mysqli_stmt_bind_param($stmt, str_repeat("s", count($params)), ...$params);
    }
    // Execute it and get results if there are any
    mysqli_stmt_execute($stmt);

    if ($result = mysqli_stmt_get_result($stmt)) {
        $row = mysqli_fetch_array($result, MYSQLI_BOTH);
        
        // echo $result->num_rows;
        // print_r($data);
        // echo $data[0]['name'];
        return $row;
    }
    // If the query was INSERT or UPDATE then return TRUE
    echo "Done";
    return TRUE;
}

?>

我希望能够返回新插入列的 id。 insert_id 不起作用。无论如何都可以在不使用其他查询的情况下返回它?

更新

我试图做的就是写这篇文章对我自己来说是安全的

$sql = "sql stmt";
$result = mysqli_query($conn, $sql);
if(!$result){
  // do something
} else{
  // do something else
}

我想把上面的块放在一个安全的函数中,并避免使用mysqli_real_escape()

最终目标 如果我的 sql stmt 被选中,我的最终目标是获取返回的数组。如果 stmt 是插入的,我想获取新插入行的 id。应该返回此信息。

更新

错误是返回值必须为 NULL。不对。最后一个问题是我试图获取新插入行的 id。但我不知道如何在不执行另一个查询的情况下做到这一点。有什么想法吗?

【问题讨论】:

  • @Dharman 这是您在上一个问题中为我编写的代码。你写的那个是面向对象的。我试图将其转换为程序。这是另一个问题的链接link
  • 您为什么要努力使其程序化?
  • 在您之前的代码中。你写了return TRUE。所以我刚从你那里得到它。是的,我有不止一个分贝
  • @Dharman 请查看更新
  • 那你有什么建议?对此我不确定。我在您的个人资料中看到 bin_param 比 real_escaped 字符串更好。所以我正在学习如何使用它。

标签: php mysqli


【解决方案1】:

要获取 ID,您只需在正确的 mysqli 对象上使用 $db1-&gt;insert_id;

注意事项:

  1. 不要在函数内部打开连接。您只需要打开一次连接。然后,每当您调用此函数时,您都会将正确的连接作为参数传递。

  2. 这个函数应该只返回值或者什么都不返回。它永远不应该返回 true 或 false。

  3. 我不建议在一个脚本中使用多个数据库,但如果必须的话,您应该为每个脚本使用单独的 mysqli 对象。

<?php

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
// db 1
$db1 = new mysqli('localhost', 'user', 'pass', 'db1');
$db1->set_charset('utf8mb4'); // always set the charset
// db 2
$db2 = new mysqli('localhost', 'user', 'pass', 'db2');
$db2->set_charset('utf8mb4'); // always set the charset

// Test:
$sql = "INSERT INTO `customers`(`name`, `email`, `phn_num`) VALUES (?, ?, ?)";
$params = array("Assad Rajab", "email@gmail.com", "0123456789");
$cus_id = fetchSingleRow($db1, $sql, $params);

// get the auto generated ID:
$id =  $db1->insert_id;
    
/**
 * Fetches a single row from the database
 *
 * @param \mysqli $conn This is the valid mysqli object with open connection to a DB
 * @param string $sql   Your SQL query with placeholders
 * @param array $params An array of parameters to be bound. [optional]
 * @return array|null   This function will return an array representing a single row from the result or nothing at all.
 */
function fetchSingleRow(\mysqli $conn, string $sql, array $params = []): ?array {
    // Prepare statement:
    $stmt = mysqli_prepare($conn, $sql);
    // If the statement has parameters then bind them all now
    if ($params) {
        mysqli_stmt_bind_param($stmt, str_repeat("s", count($params)), ...$params);
    }
    // Execute it and get results if there are any
    mysqli_stmt_execute($stmt);

    if ($result = mysqli_stmt_get_result($stmt)) {
        $row = mysqli_fetch_array($result, MYSQLI_BOTH);
        return $row;
    }

    // nothing to return
    return null;
}

【讨论】:

  • \mysqli $conn 是什么?我正在使用超过 3 个数据库。这是我现在唯一的方法。我不太擅长数据库结构。所以这是唯一的方法......
  • 这会返回新插入的行ID吗?
  • @AssadRajab 否,该函数返回单行。新行的 ID 将保存在 mysqli 类的属性中。 $db1-&gt;insert_id
  • 我一直在寻找的想法是,如果选择了 stmt,则创建一个返回多行的函数。如果 stmt 是插入的。设置或返回 id。这个功能可以做到吗?打扰了
  • @AssadRajab 不要这样做。这是没有意义的,一个函数实际上应该只返回一种类型的值。不要混合它。 ID 保存在 mysqli 类的属性中,因此函数实际上没有理由返回它。该函数应该只执行它。
猜你喜欢
  • 1970-01-01
  • 2017-04-22
  • 1970-01-01
  • 2018-08-21
  • 1970-01-01
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
相关资源
最近更新 更多