You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CodeIgniter 4.4.5无法捕获MySQL重复条目异常求助

CodeIgniter v4.4.5无法捕获MySQL重复条目异常问题

我正在使用CodeIgniter v4.4.5,遇到了一个问题:当MySQL出现重复条目错误时,框架只会记录异常日志,不会将异常抛回至控制器,导致我无法在控制器中捕获并处理该异常,返回用户提示信息。

排查到的框架代码逻辑

异常首先在CodeIgniter\Database\MySQLi\Connection.php的execute方法中触发:

protected function execute(string $sql)
{
    while ($this->connID->more_results()) {
        $this->connID->next_result();
        if ($res = $this->connID->store_result()) {
            $res->free();
        }
    }

    try {
        return $this->connID->query($this->prepQuery($sql), $this->resultMode);
    } catch (mysqli_sql_exception $e) {
        log_message('error', (string) $e);

        if ($this->DBDebug) {
            throw new DatabaseException($e->getMessage(), $e->getCode(), $e);
        }
    }

    return false;
}

当DBDebug设置为TRUE时,异常会传递到CodeIgniter\Database\BaseConnection,但这里异常被捕获后仅设置resultID = false,没有继续向上抛出:

// Run the query for real
try {
    $exception      = null;
    $this->resultID = $this->simpleQuery($query->getQuery());
} catch (DatabaseException $exception) {
    $this->resultID = false;
}

我的控制器代码(无法捕获异常)

try{
 //...其他代码
  $modelProducts = new ProductsModel();
            $modelProducts->insert($data_product);
 //此时日志已记录重复条目异常,但代码仍继续执行
}
catch(DatabaseException $e)
{            
    //这段代码从未执行,即使日志里有MySQL异常记录
    log_message('error',  __NAMESPACE__ . " > " . __FUNCTION__ . $e);
}
catch(Exception $e) {  
    //这段代码也从未执行
    log_message('error', __NAMESPACE__ . " > " . __FUNCTION__ . $e);
}

解决方案

方案1:通过模型错误信息判断(推荐,无需修改框架)

CodeIgniter的模型在插入失败时,会保存错误信息,可通过errors()方法获取,据此判断是否为重复条目:

$modelProducts = new ProductsModel();
if (!$modelProducts->insert($data_product)) {
    $errors = $modelProducts->errors();
    // 检查是否是重复条目错误(匹配MySQL重复条目提示)
    foreach ($errors as $error) {
        if (strpos($error, 'Duplicate entry') !== false) {
            // 处理重复条目逻辑
            log_message('error', '重复条目异常:' . $error);
            // 返回用户提示,比如:
            // return $this->response->setJSON(['status' => 'error', 'message' => '该条目已存在']);
            break;
        }
    }
}

方案2:直接使用数据库连接执行查询并捕获异常

绕过模型,直接调用数据库连接执行插入,这样可以捕获到异常:

$db = \Config\Database::connect();
try {
    // 替换为你的插入语句和参数
    $db->query("INSERT INTO products (name, ...) VALUES (:name, ...)", $data_product);
} catch (\CodeIgniter\Database\Exceptions\DatabaseException $e) {
    // MySQL重复条目错误码为1062
    if ($e->getCode() == 1062) {
        log_message('error', __NAMESPACE__ . " > " . __FUNCTION__ . $e->getMessage());
        // 返回用户提示
    }
}

方案3:修改框架代码(不推荐)

如果一定要通过try/catch捕获模型抛出的异常,可以修改CodeIgniter\Database\BaseConnection中的代码,在捕获异常后重新抛出:

// Run the query for real
try {
    $exception      = null;
    $this->resultID = $this->simpleQuery($query->getQuery());
} catch (DatabaseException $exception) {
    $this->resultID = false;
    throw $exception; // 新增此行,重新抛出异常
}

注意:修改框架文件会导致后续框架升级时丢失修改,需谨慎操作。

内容的提问来源于stack exchange,提问作者Jay85

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 00:43:22