You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CodeIgniter 4 问题:数据无法插入pemesanan表求助

问题描述

我遇到了数据无法插入pemesanan表的问题。已通过dd($data)确认数据为数组格式,但调用$PemesananModel->save($data)后,数据并未插入到数据库中,恳请协助解决。


控制器

数据从produk1()方法传递至视图,再由视图提交至add_pesan方法:

public function produk1()
{
    $model = new ProdukModel();
    $pemesananModel = new PemesananModel();

    $data['getProduk'] = $model->getData();
    $data['cart'] = \Config\Services::cart();

    $noAntrian = $pemesananModel->generateNoAntrian();
    $idKaryawan = 1;
    $idPemesan = "P" . date('md') . rand(3, 1);


    $data['id_pemesan'] = $idPemesan;
    $data['id_pelanggan'] = session()->get('id_pelanggan');
    $data['id_karyawan'] = $idKaryawan;
    $data['no_antrian'] = $noAntrian;
    $data['tgl'] = date('Y-m-d');
    $data['status_pembayaran'] = "cash";
    $data['status_pemesanan'] = 'Dalam Antrian';



    $data['nama_pelanggan'] = session()->get('nama_pelanggan');
    $data['no_hp'] = session()->get('no_hp');

    echo view('user/produk', $data);
}

public function add_pesan()
{
    $pemesananModel = new PemesananModel();

    $id_pemesan = $this->request->getPost('id_pemesan');
    $id_pelanggan = (int)session()->get('id_pelanggan');
    $id_karyawan = 1;
    $noAntrian = (int)$pemesananModel->generateNoAntrian();
    $tgl = $this->request->getPost('tgl');
    $status_pembayaran = $this->request->getPost('status_pembayaran');
    $status_pemesanan = $this->request->getPost('status_pemesanan');

    $data = [
        'id_pemesan' => $id_pemesan,
        'id_pelanggan' => $id_pelanggan,
        'id_karyawan' => $id_karyawan,
        'no_antrian' => $noAntrian,
        'tgl' => $tgl,
        'status_pembayaran' => $status_pembayaran,
        'status_pemesanan' => $status_pemesanan
    ];

    log_message('info', 'Data to be saved: ' . print_r($data, true));

    if ($pemesananModel->save($data)) {
        session()->setFlashdata('pesan', 'Berhasil Pesan');
    } else {
        $errors = $pemesananModel->errors();
        log_message('error', 'Failed to save data: ' . print_r($errors, true));
        session()->setFlashdata('error', 'Gagal Pesan: ' . implode(', ', $errors));
    }
    return redirect()->to('/produk1');
}

视图

接收produk1传递的数据并提交至add_pesan:

<form action="/add_pemesanan" method="post">
    <input type="hidden" name="id_pemesan" value="<?= $id_pemesan ?>" class="hidden">
    <input type="hidden" name="id_pelanggan" value="<?= $id_pelanggan ?>" class="hidden">
    <input type="hidden" name="id_karyawan" value="<?= $id_karyawan ?>" class="hidden">
    <input type="hidden" name="no_antrian" value="<?= $no_antrian ?>" class="hidden">
    <input type="hidden" name="tgl" value="<?= $tgl ?>" class="hidden">
    <input type="hidden" name="status_pembayaran" value="<?= $status_pembayaran ?>" class="hidden">
    <input type="hidden" name="status_pemesanan" value="<?= $status_pemesanan ?>" class="hidden">
    <button type="submit" id="cartIcon" class="flex items-center p-4 bg-indigo-500 text-white font-semibold rounded hover:bg-indigo-600">
        <i class="fas fa-shopping-cart"><?= $all_item; ?></i>
    </button>
</form>

模型

<?php

namespace App\Models;

use CodeIgniter\Model;

class PemesananModel extends Model
{
    protected $table = 'pemesanan';
    protected $primaryKey = 'id_pemesan';
    protected $allowedFields = [
        'id_pemesan',
        'id_pelanggan',
        'id_karyawan',
        'no_antrian',
        'tgl',
        'status_pembayaran',
        'status_pemesanan'
    ];

    public function generateNoAntrian()
    {
        $lastOrder = $this->orderBy('id_pemesan', 'DESC')->first();
        if ($lastOrder) {
            $lastNoAntrian = (int)substr($lastOrder['no_antrian'], 2);
            $newNoAntrian = $lastNoAntrian + 1;
        } else {
            $newNoAntrian = 1;
        }
        return str_pad($newNoAntrian, 4, '0', STR_PAD_LEFT);
    }

    public function getData($id = false)
    {
        $builder = $this->db->table($this->table);
        $builder->select('pemesanan.no_antrian, pelanggan.no_hp AS no_hp, pemesanan.tgl, pemesanan.status_pembayaran, pemesanan.status_pemesanan, pelanggan.nama_pelanggan AS nama_pelanggan, karyawan.nama AS nama_karyawan');
        $builder->join('pelanggan', 'pelanggan.id_pelanggan = pemesanan.id_pelanggan');
        $builder->join('karyawan', 'karyawan.id_karyawan = pemesanan.id_karyawan');

        if ($id !== false) {
            $builder->where('pemesanan.id_pemesan', $id);
        }
        $query = $builder->get();
        return $query->getResult();
    }

    public function getData_for_pelanggan($id = false)
    {
        if ($id === false) {
            return $this->findAll();
        } else {
            return $this->getWhere(['id_pemesan' => $id]);
        }
    }
}

路由

$routes->get('/produk1', 'AdminController::produk1');
$routes->match(['get', 'post'], '/add_pemesanan', 'AdminController::add_pesan');

数据库结构

数据库结构截图


问题排查与解决方法

  1. no_antrian类型不匹配
    数据库中no_antrian是varchar类型,但add_pesan中把生成的带前导零的字符串强制转为int,导致数据格式丢失。去掉强制转换:

    $noAntrian = $pemesananModel->generateNoAntrian();
    
  2. 主键id_pemesan重复
    当前idPemesan生成逻辑"P" . date('md') . rand(3,1)极易重复,优化生成规则:

    $idPemesan = "P" . date('YmdHis') . rand(1000, 9999);
    
  3. 缺少CSRF令牌
    CodeIgniter默认启用CSRF保护,表单未提交令牌会被拦截,添加令牌字段:

    <input type="hidden" name="<?= csrf_token() ?>" value="<?= csrf_hash() ?>">
    
  4. id_pelanggan为空验证
    未登录时session()->get('id_pelanggan')为null,转int后变为0,若数据库字段不允许空则插入失败,添加登录校验:

    $id_pelanggan = session()->get('id_pelanggan');
    if (!$id_pelanggan) {
        session()->setFlashdata('error', '请先登录');
        return redirect()->to('/login');
    }
    $id_pelanggan = (int)$id_pelanggan;
    
  5. 查看错误日志
    检查writable/logs目录下的日志文件,根据log_message记录的错误信息定位具体问题,或直接打印$pemesananModel->errors()获取验证失败详情。


内容的提问来源于stack exchange,提问作者AtepRiandi Pahmi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 12:04:57