如何在 AJAX success 中获取插入记录的 id 并传给打印页
结论
每插入一条记录,就用 CodeIgniter 的 $this->db->insert_id() 获取该记录的自增主键,并把所有 id 保存到数组中。Controller 将数组以 JSON 返回后,AJAX 的 success 回调可以把这些 id 编码到打印页 URL 中。
批量插入最好放在数据库事务中处理。只要有一条记录插入失败,就回滚整个事务,避免部分数据已经写入却仍然返回成功。
Model:插入后返回 id
假设 payment_rec_allocn 表使用自增主键,Model 应返回新记录的 id,而不是只返回 true:
public function insertPaymentAllocation($data)
{
if (!$this->db->insert('payment_rec_allocn', $data)) {
return false;
}
return (int) $this->db->insert_id();
}
insert_id() 应紧跟在对应的 insert() 后面调用,以免后续数据库操作影响它返回的值。
Controller:收集并返回全部 id
批量插入时,把每次得到的 id 加入数组:
public function createPaymentAllocation()
{
$biltyIds = $this->input->post('due_ids');
$agent = $this->input->post('agent');
$dueTo = $this->input->post('due_to');
if (!is_array($biltyIds) || empty($biltyIds)) {
return $this->output
->set_content_type('application/json')
->set_output(json_encode([
'PaymentRecAllocation' => [
'form_status' => false,
'form_message' => 'No records were selected.',
'inserted_ids' => [],
],
]));
}
$insertedIds = [];
$this->db->trans_begin();
foreach ($biltyIds as $biltyId) {
$row = [
'pay_rec_alloc_agent' => $agent,
'pay_dueto' => $dueTo,
'mr_no' => $biltyId,
];
$insertId = $this->PayRecAllModel
->insertPaymentAllocation($row);
if ($insertId === false) {
$this->db->trans_rollback();
return $this->output
->set_content_type('application/json')
->set_output(json_encode([
'PaymentRecAllocation' => [
'form_status' => false,
'form_message' => 'Something went wrong.',
'inserted_ids' => [],
],
]));
}
$insertedIds[] = $insertId;
}
if ($this->db->trans_status() === false) {
$this->db->trans_rollback();
return $this->output
->set_content_type('application/json')
->set_output(json_encode([
'PaymentRecAllocation' => [
'form_status' => false,
'form_message' => 'Something went wrong.',
'inserted_ids' => [],
],
]));
}
$this->db->trans_commit();
return $this->output
->set_content_type('application/json')
->set_output(json_encode([
'PaymentRecAllocation' => [
'form_status' => true,
'form_message' => 'Payment Recovery has been successfully allocated.',
'inserted_ids' => $insertedIds,
],
]));
}
如果这次插入产生的数据库主键是 101、102、103,响应内容如下:
{
"PaymentRecAllocation": {
"form_status": true,
"form_message": "Payment Recovery has been successfully allocated.",
"inserted_ids": [101, 102, 103]
}
}
inserted_ids 保存的是新插入记录的数据库主键,不是原来的 MR No 7、8、9。
AJAX:接收 id 并传给打印页
设置 dataType: "json" 后,jQuery 会自动把响应解析为对象。跳转到打印页之前,可以把 id 数组转换成逗号分隔的字符串:
success: function (data) {
var result = data.PaymentRecAllocation;
if (result.form_status === true) {
var insertedIds = result.inserted_ids;
alertify.confirm(
'Payment Recovery Allocation',
'Do you want to print?',
function () {
var ids = encodeURIComponent(insertedIds.join(','));
window.location.href =
'crossing/payment_rec_allocation/' +
'PaymentRecAllocationController/' +
'printCollectionRecPage?ids=' + ids;
},
function () {
window.location.reload();
}
);
} else {
alertify.error(result.form_message);
$('#allocate').prop('disabled', false);
}
},
error: function () {
alertify.error('Request failed.');
$('#allocate').prop('disabled', false);
}
生成的打印地址类似:
crossing/payment_rec_allocation/PaymentRecAllocationController/printCollectionRecPage?ids=101%2C102%2C103
打印方法:读取并校验 id
打印页 Controller 读取查询参数后,将字符串拆成 id 数组:
public function printCollectionRecPage()
{
$idsString = (string) $this->input->get('ids', true);
$ids = array_values(array_filter(
array_map('intval', explode(',', $idsString)),
static function ($id) {
return $id > 0;
}
));
if (empty($ids)) {
show_error('No valid allocation ids were provided.', 400);
return;
}
$data['allocations'] = $this->PayRecAllModel
->getPaymentAllocationsByIds($ids);
$this->load->view('payment_rec_allocation/print_collection', $data);
}
对应的 Model 查询可以这样写:
public function getPaymentAllocationsByIds(array $ids)
{
return $this->db
->where_in('id', $ids) // 将 id 替换为表中实际的主键字段名
->get('payment_rec_allocn')
->result_array();
}
需要注意的问题
表必须有自增主键
$this->db->insert_id() 用于获取数据库生成的自增 id。如果主键是 UUID,或者由业务代码生成,应在插入前生成主键,然后直接将它加入 $insertedIds。
不要只判断最后一次插入结果
原代码在循环结束后只检查 $modelResult,因此只能判断最后一条记录是否插入成功。如果前面的某条记录失败,程序仍可能把整个批次当作成功。使用事务后,批量操作要么全部提交,要么全部回滚。
请求字段名称要保持一致
前端示例提交的是:
var rec_type = $('#rec_type').val();
formData.append('rec_type', rec_type);
Controller 读取的却是:
$dueTo = $this->input->post('due_to');
这两个字段名并不一致。如果 pay_dueto 实际对应 rec_type,Controller 应改为:
$dueTo = $this->input->post('rec_type');
也可以让前端改为提交 due_to:
formData.append('due_to', rec_type);
JSON 中使用布尔值
JSON 响应应返回真正的布尔值:
'form_status' => true
前端再用严格比较判断:
result.form_status === true
不要混用字符串 'true'、'false' 和布尔值,否则判断结果容易出错。
不要信任 URL 中传入的 id
打印方法还需要检查当前用户是否有权访问这些记录。把字符串转换为整数只能过滤非法格式,不能代替权限校验。
如果一次可能插入大量记录,不适合把所有 id 都放进 URL。可以生成一个批次号,例如 allocation_batch_id。打印页只接收批次号,再从数据库中查询该批次的全部记录。
备注:内容仅供参考。
