CodeIgniter中数据库数据获取异常及邮件发送失败问题求助
看起来你遇到了几个核心问题,导致邮件无法发送还出现了非对象的PHP提示,咱们一步步来解决:
1. 修复模型的查询逻辑(解决非对象错误)
你的App_model里的send_mail方法没有接收$appointment_id参数,所以它会返回所有预约记录,而不是你指定ID的那一条。当你在控制器里尝试访问$appointment[0]->cust_name时,如果查询结果为空(或者没有匹配的ID),$appointment[0]就不是对象,自然会触发那个Notice错误。
修改App_model.php的send_mail方法,添加参数和WHERE条件:
public function send_mail($appointment_id) { $query=$this->db ->select('*, employee.name_emp as emp_name, customer.name as cust_name, customer.email as cust_email, servicetype.name_set as s_name, serviceplan.price as p_rice') ->from('appointment') ->join('customer', 'customer.id= appointment.name_app') ->join('servicetype', 'servicetype.id_set= appointment.sertype') ->join('employee', 'employee.id_emp= appointment.emp') ->join('serviceplan', 'serviceplan.price=appointment.price_app') // 取消注释,关联服务价格表 ->where('appointment.id', $appointment_id) // 关键:筛选指定ID的预约 ->get(); return $query->row(); // 用row()返回单条记录,无需用数组索引访问 }
这里用row()代替result(),因为我们只需要一条预约记录,后续在控制器里可以直接通过对象属性访问数据,不用再取数组下标。
2. 修复控制器的邮件内容与逻辑(解决邮件无法发送)
你直接把数组$message传给了$this->email->message(),但CodeIgniter的邮件类需要的是字符串(HTML或纯文本),不是数组。另外,还要先判断查询结果是否存在,避免再次触发非对象错误。
修改App_controller.php的sendmail方法:
function sendmail($appointment_id){ $config = Array( 'protocol' => 'smtp', 'smtp_host' => 'ssl://smtp.googlemail.com', 'smtp_port' => 465, 'smtp_user' => '你的谷歌邮箱地址', 'smtp_pass' => '你的谷歌应用专用密码', // 注意:不能用普通账号密码,后续说明 'mailtype' => 'html', 'charset' => 'utf-8' // 替换为utf-8避免乱码 ); $this->load->library('email', $config); $this->email->set_newline("\r\n"); $this->load->model('App_model'); $appointment = $this->App_model->send_mail($appointment_id); // 先判断是否获取到有效预约数据 if(!$appointment){ echo "找不到对应的预约记录,请检查ID是否正确"; return; } // 构建HTML格式的邮件内容 $message = '<h2>预约确认通知</h2>'; $message .= '<p>尊敬的 '.$appointment->cust_name.':</p>'; $message .= '<p>您的预约已成功提交,以下是预约详情:</p>'; $message .= '<ul>'; $message .= '<li>服务类型:'.$appointment->s_name.'</li>'; $message .= '<li>服务员工:'.$appointment->emp_name.'</li>'; $message .= '<li>预约日期:'.$appointment->date.'</li>'; $message .= '<li>预约时间:'.$appointment->time.'</li>'; $message .= '<li>服务价格:'.$appointment->p_rice.'</li>'; $message .= '</ul>'; $message .= '<p>感谢您的信任,我们期待为您服务!</p>'; $this->email->from('你的邮箱地址', '你的店铺/品牌名称'); $this->email->to($appointment->cust_email); // 发送给客户的真实邮箱 $this->email->subject('Your Appointment Confirmation'); $this->email->message($message); // 添加调试输出,快速定位发送失败原因 if(!$this->email->send()){ echo "<h3>邮件发送失败,错误信息:</h3>"; echo $this->email->print_debugger(); } else { echo "预约确认邮件已成功发送给客户!"; } }
注意几个关键修正:
- 将收件人从固定的
xxx改为从数据库获取的客户邮箱$appointment->cust_email - 把邮件内容改为HTML字符串,符合
mailtype => html的配置要求 - 添加了数据存在性判断,避免空对象报错
- 增加了调试输出,方便排查SMTP连接或邮件内容的问题
3. 修复谷歌SMTP的权限问题
现在谷歌邮箱默认禁止使用普通账号密码通过SMTP发送邮件,你需要完成以下两步:
- 开启谷歌账号的两步验证
- 生成一个应用专用密码(App Password),用这个密码替换配置里的
smtp_pass
如果跳过这一步,SMTP连接会直接失败,邮件无法发送。
4. 额外调试建议
如果还是有问题,可以开启CodeIgniter的调试模式查看详细错误:
在application/config/config.php中设置:
$config['debug'] = true;
另外,$this->email->print_debugger()会输出SMTP连接的完整日志,包括连接状态、错误代码等,这是排查邮件发送问题的核心工具。
内容的提问来源于stack exchange,提问作者Sagar Parikh

