PAYATHON 2026

如何在 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。打印页只接收批次号,再从数据库中查询该批次的全部记录。

备注:内容仅供参考。