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
相关产品推荐
相关产品推荐

