使用SQLSRV+AJAX+CI调用存储过程时触发result_array()布尔值调用错误
嘿,我来帮你搞定这个头疼的问题!你遇到的Fatal error: Call to a member function result_array() on boolean,本质是因为$this->db->query()执行失败时返回了false,这时候你去调用result_array()自然就报错了。而移除这个方法后AJAX进不了回调,是因为没有返回有效的JSON数据。咱们一步步来修复:
1. 先解决SQL注入风险+语法错误问题
你现在直接把参数拼进SQL语句里,不仅有严重的SQL注入风险,如果用户输入的内容里包含单引号(比如名字是O'Neil),还会直接导致SQL语法错误,让query()返回false。赶紧换成CodeIgniter的查询绑定功能,安全又可靠:
修改模型里的方法:
public function set_add_user($param){ // 使用?作为占位符,CI会自动处理参数转义 $sql = "exec set_add_user_i ?, ?"; // 把参数放进数组里传给query方法 $query = $this->db->query($sql, array($param["firstname"], $param["lastname"])); // 先判断查询是否成功 if ($query === false) { // 返回包含错误信息的数组,方便AJAX处理 return array('result' => 'Database Error: ' . $this->db->error()['message']); } return $query->result_array(); }
2. 调整存储过程,确保始终返回结果集
你的存储过程在try块里只有INSERT操作,没有返回任何结果。SQL Server执行INSERT后会默认返回一个“影响行数”的结果,但CodeIgniter对这种结果的处理可能不太一致,导致query()无法正确解析出结果集,最终返回false或者没有可用的result_array()。
修改存储过程,在成功时也返回明确的标识:
create procedure [dbo].[set_add_user_i] @firstname varchar(50), @lastname varchar(50) as begin try insert into [Users](Firstname,Lastname) values(@firstname,@lastname) -- 新增成功结果返回,和catch块的格式保持一致 select 'Success' as result; end try begin catch select 'Error' as result; end catch
这样不管成功还是失败,存储过程都会返回一个包含result字段的结果集,CI的query()就能正确获取到,不会返回false了。
3. 确保AJAX能拿到有效JSON
之前你移除result_array()后,模型可能返回的是false或者空值,json_encode(false)虽然是有效的JSON,但你的AJAX逻辑里判断if(evt),而"false"在JS里是字符串,会被当成true,但如果模型没有返回任何数组,json_encode()可能输出null,这时候AJAX的success回调可能因为数据格式问题进入error。
现在调整后的模型不管成功失败都会返回数组,json_encode()后会输出类似[{"result":"Success"}]或者[{"result":"Error"}]的有效JSON,AJAX就能正常进入回调了。
额外调试技巧
如果还是有问题,可以先在模型里打印出执行的SQL语句,看看是否正确:
echo $this->db->last_query(); exit;
然后把这个SQL语句复制到SSMS里执行,看看能不能正常运行,这样就能快速定位是存储过程的问题还是CI调用的问题。
内容的提问来源于stack exchange,提问作者SCrub

