
本文详解 codeigniter 项目中注册时生成并存储 otp 失败的根本原因——模型方法参数传递错误,并提供修正后的控制器与模型代码、安全建议及完整流程说明。
在 CodeIgniter 开发中,常见场景是用户提交邮箱后,系统生成 8 位数字 OTP 并发送至该邮箱,同时将邮箱与 OTP 一同存入数据库(如 cred 表)用于后续验证。但如您所遇问题:邮件成功发出、邮箱入库成功,而 OTP 却未写入数据库——这通常并非逻辑或邮件配置问题,而是数据插入时参数结构错误导致的静默失败。
关键问题定位在控制器 auth.php 的 register() 方法中这一行:
$data = $this->user_model->insert('cred', ['email' => $to], ['otp' => ($newotp)]);
此处调用了 user_model->insert() 方法,却传入了 三个参数:$table、$data1、$data2。而您的模型方法定义为:
public function insert($table, $data = array())
即仅接受两个参数:表名 + 待插入数据数组。第三个参数 [‘otp’ => …] 被完全忽略,因此只有 [’email’ => $to] 被传入并执行插入,OTP 自然不会入库。
✅ 正确做法是:将 email 和 OTP 合并为单个关联数组,作为第二个参数传入:
$data = $this->user_model->insert('cred', ['email' => $to, 'otp' => $newotp]);
同时,建议优化模型方法,增强健壮性与可维护性:
✅ 修正后的 user_model.php(推荐):
public function insert($table, $data = []) { if (empty($data)) { return FALSE; } $this->db->insert($table, $data); return $this->db->affected_rows() === 1 ? $this->db->insert_id() : FALSE; }
此外,还需注意以下几点以保障功能安全与可用性:
- ? OTP 安全性:当前 OTP 以明文形式存入数据库且通过邮件明文发送,存在严重安全隐患。生产环境务必:
- ? 邮件发送校验:$this->Others->send_email() 返回值未被检查。建议添加判断,失败时记录日志并回滚或提示用户重试:
if (!$mail) { log_message('error', 'OTP email failed for: ' . $to); $this->session->set_flashdata('error', '验证码发送失败,请重试'); redirect(base_url() . 'auth/register'); } - ? OTP 生成优化:当前 rand() 在某些环境下可能不够随机。推荐使用更安全的 random_int()(PHP 7+):
$newotp = ''; for ($i = 0; $i < 8; $i++) { $newotp .= random_int(0, 9); }
最后,完整修正后的控制器逻辑应如下(精简关键部分):
public function register() { $to = trim($this->input->post('email')); if (!filter_var($to, FILTER_VALIDATE_EMAIL)) { $this->session->set_flashdata('error', '邮箱格式不正确'); redirect(base_url() . 'auth/register'); return; } // 安全 OTP 生成(PHP 7+) $newotp = str_pad(random_int(0, 99999999), 8, '0', STR_PAD_LEFT); // 发送邮件 $subject = "OTP FOR LOGIN"; $message = "Dear User,
Thanks for requesting OTP.
Your verification code is: {$newotp}.
this code expires in 5 minutes.
— Auto-generated"; if (!$this->Others->send_email($to, $subject, $message)) { log_message('error', "Email send failed for {$to}"); $this->session->set_flashdata('error', '验证码发送失败,请稍后重试'); redirect(base_url() . 'auth/register'); return; } // 插入邮箱 + OTP(单数组!) $result = $this->user_model->insert('cred', [ 'email' => $to, 'otp' => $newotp, // 生产环境请替换为 password_hash($newotp, PASSWORD_ARGON2ID) 'created_at' => date('Y-m-d H:i:s') ]); if ($result) { $this->session->set_flashdata('success', '验证码已发送,请查收邮箱'); } else { $this->session->set_flashdata('error', '注册信息保存失败'); } redirect(base_url() . 'auth/login'); }
总结:一次看似微小的参数误传(多传一个数组),就可能导致核心认证流程断裂。排查此类问题时,应优先审查方法签名与实际调用是否一致,再结合日志与数据库操作结果交叉验证。遵循“单一职责+明确契约”的编码原则,可大幅提升 CodeIgniter 应用的稳定性与可维护性。