如何在 Codeigniter 中的数据库中插入数组?

Posted

技术标签:

【中文标题】如何在 Codeigniter 中的数据库中插入数组?【英文标题】:How to insert an array in database in Codeigniter? 【发布时间】:2021-02-07 02:55:09 【问题描述】:

我在 Codeigniter 中的数据库中插入数组时遇到问题,我尝试了以下方式,但它给出了错误“消息:非法字符串偏移 'year'”、“消息:非法字符串偏移 'month'”等等。 ..,我真的很困惑如何解决这个问题,请帮忙。

这是表格:

<form action="<?php echo base_url();?>hr/Home/store_attendance" method="post"
id="student_attendance_entry">
<input type="hidden" name="year" value="<?php echo $year; ?>" />
<input type="hidden" name="month" value="<?php echo $month; ?>" />
<?php foreach($staffs as $staff): ?>
<table class="table table-striped table-bordered table-hover attendance_entry"
    style="border:initial;border: 1px solid #ddd;" id="sample_editable_2">
    <thead>
        <tr>
            <th style="width: 50px !important;">شماره</th>
            <th align="center" style="width:auto%">آی دی</th>
            <th align="center" style="width:15%">نام</th>
            <th align="center" style="width:15%;"> ولد</th>
            <th align="center" style="width:auto">حاضر</th>
            <th align="center" style="width:auto">غیر حاضر</th>
            <th align="center" style="width:auto">توضیحات</th>
        </tr>
    </thead>
    <tbody>
        <?php $a=1; foreach($staffs as $st):?>
        <tr>
            <td align="center" style="font-size: 11px"><?php echo $a;?></td>
            <td align="center" style="font-size: 11px"><?php echo $st['s_id'];?></td>
            <td align="center"><?php echo $st['dari_name'];?></td>
            <td align="center"><?php echo $st['dari_fName'];?></td>
            <td>
                <input type="number" min="0" class="form-control" name="total_present_day[]"
                    value="<?php if($st['total_present']==null)echo '';else echo $st['total_present'];?>"
                    data="<?php echo $a;?>">

                <input type="hidden" name="salary_type[]" id="salary_type" value="<?php echo $st['salary_type']?>">
            </td>
            <td>
                <input type="number" min="0" class="form-control" name="total_absent_day[]"
                    value="<?php if($st['absent']==null)echo '';else echo $st['absent'];?>"
                    data="<?php echo $a;?>">
                <input type="hidden" class="form-control" name="staff_id[]" value="<?php echo $st['s_id'];?>">

            </td>
            <td>
                <textarea min="0" class="form-control" name="memo[]"
                    colspan='3' rowspan="1"
                    data="<?php echo $a;?>"><?php if($st['memo']==null)echo '';else echo $st['memo'];?></textarea>
               

            </td>
        </tr>
        <?php $a++;endforeach;?>
    </tbody>
</table>

<?php endforeach; ?>
<br>
<div class="form-actions right">
    <a href="<?php echo base_url();?>student/school/attendance" class="btn default" data-dismiss="modal"><i
            class="fa fa-close"></i> بستن</a>
    <input type="submit" name="save" class="btn blue" value="ذخیره" />
</div>

这是控制器:

 public function store_attendance()

    $data=array(

        'year' =>  $this->input->post('year'),
        'month' => $this->input->post('month'),
        'staff_id' => $this->input->post('staff_id'),
        'total_present_day' => $this->input->post('total_present_day'),
        'total_absent_day'=>$this->input->post('total_absent_day'),
        'salary_type'=>$this->input->post('salary_type'),
        'memo'=>$this->input->post('memo')
    );
    $this->dd($data);
    // $this->dd($class);
    $insert_att = $this->stuff_model->add_staff_attendance($data);
    // var_dump($insert_att);
    if($insert_att)
    
        echo redirect(base_url().'hr/register_employee_attendance');
    
   

这是模型:

public function add_staff_attendance($data)
  
      $this->db->trans_begin();

      foreach ($data['total_present_day'] as $key => $value) 
          
          
  $dataToSave = array(
   'year' =>  $value['year'],
   'month' => $value['month'],
   'type_id'=>$value['salary_type'][$key],
   'total_present' => $value['total_present_day'][$key],
   'absent'=>$value['total_absent_day'][$key],
   'memo'=>$value['memo'][$key],
   'staf_id' => $value['staff_id'][$key]
 );
      
        $this->db->insert('staff_attendance', $dataToSave);
    
          if ($this->db->trans_status() === false) 
              $this->db->trans_rollback();
              return false;
           else 
              $this->db->trans_commit();
              return true;
          
      

我在控制器中调用了$this-&gt;dd($data),这是输出:

array (
'Total' => 7,
)
array (
  'year' => '1400',
  'month' => '2',
  'staff_id' => 
     array (
       0 => '3',
     ),
   'total_present_day' => 
     array (
       0 => '26',
   ),
   'total_absent_day' => 
      array (
        0 => '0',
      ),
   'salary_type' => '1',
   'memo' => 
    array (
      0 => 'dds',
    ),
)

这是 echo '&lt;pre&gt;'; print_r($data); echo '&lt;/pre&gt;';在模型中的结果:

 Array
 (
   [year] => 1400
   [month] => 1
   [staff_id] => Array
     (
       [0] => 3
       [1] => 1
     )

[total_present_day] => Array
    (
        [0] => 26
        [1] => 20
    )

[total_absent_day] => Array
    (
        [0] => 0
        [1] => 6
    )

[salary_type] => Array
    (
        [0] => 1
        [1] => 1
    )

[memo] => Array
    (
        [0] => asfd
        [1] => saef
    )

    )
    Array
    (
    [year] => 1400
    [month] => 1
    [staff_id] => Array
    (
        [0] => 3
        [1] => 1
    )

[total_present_day] => Array
    (
        [0] => 26
        [1] => 20
    )

[total_absent_day] => Array
    (
        [0] => 0
        [1] => 6
    )

[salary_type] => Array
    (
        [0] => 1
        [1] => 1
    )

[memo] => Array
    (
        [0] => asfd
        [1] => saef
    )

 )

【问题讨论】:

为什么需要循环播放? ,可以直接$data['year']等 @Jerson 因为不仅有员工要存储在数据库中,有时可能不止一个人 您知道,您的标记是无效的,因为您正在生成多个具有相同idsample_editable_2 的表。无论您使用 data="&lt;?php echo $a;?&gt;" 做什么,我都会将其删除,如果有必要,请找到更聪明的方法。 &lt;?php if($st['memo']==null)echo '';else echo $st['memo'];?&gt;(和类似的重复代码)更简单地表示为&lt;?php echo $st['memo'] ?: ''; ?&gt; ...我不相信在这种情况下你甚至需要?: '' 如果控制器都指向同一个目的地,为什么会有条件重定向? 【参考方案1】:

您提交的数据结构合理、简约但不规则。通过在视图中重新配置表单字段的name 属性,可以大大减少控制器和模型中处理代码的行数。

foeach() 循环中移动隐藏字段并声明动态索引。实际上,命名字段类似于:

<?php foreach($staffs as $index => $staff)  ?>
    <input type="hidden" name="attendance[<?php echo $index; ?>]['year']">
    <input type="hidden" name="attendance[<?php echo $index; ?>]['month']">
    <input type="number" name="attendance[<?php echo $index; ?>]['total_present']">
    <input type="hidden" name="attendance[<?php echo $index; ?>]['type_id']">
    <input type="number" name="attendance[<?php echo $index; ?>]['absent']">
    <input type="hidden" name="attendance[<?php echo $index; ?>]['staf_id']">
    <textarea name="attendance[<?php echo $index; ?>]['memo']"></textarea>
<?php  ?>

在盲目地将数据传递给模型之前,控制器需要一个验证/清理过程和一些重组。我不会进行验证/清理,但您应该迭代数据,如果任何值不合适,则拒绝保存。

控制器:

public function store_attendance(): void

    // Definitely validate and sanitize the rows of data before passing to model.
    // This shortcut is for demonstrating how to batch insert
    if ($this->stuff_model->add_staff_attendance($this->input->post('attendance'))) 
        redirect(base_url() . 'hr/home/register_employee_attendance');
     else 
        // reload view and explain what went wrong
    

型号:

public function add_staff_attendance(array $data): bool

    return $this->db->insert_batch('staff_attendance', $data);

此答案均未经过测试。


要将隐藏字段保留在循环之外,您需要将行的值组合到正确的结构中,然后再发送到batch_insertion 的模型。

$presentDays = $this->input->post('total_present_day');
if ($presentDay) 
    $rows = [];
    foreach ($presentDays as $i => $presentDay) 
        $rows[] = [
            'year' => $this->input->post('year'),
            'month' => $this->input->post('month'),
            'staf_id' => $this->input->post('staff_id')[$i],
            'total_present' => $this->input->post('total_present_day')[$i],
            'absent' => $this->input->post('total_absent_day')[$i],
            'type_id' => $this->input->post('salary_type')[$i],
            'memo' => $this->input->post('memo')[$i]
        ];
    
    
    if ($this->stuff_model->add_staff_attendance($rows)) 
        redirect(base_url() . 'hr/home/register_employee_attendance');
     else 
        // reload view and explain what went wrong
    

【讨论】:

没有必要在循环内移动隐藏文件,我尝试了另一种方法,现在它完全符合我的要求。 确实可以在不将隐藏字段移动到循环中的情况下完成。可以将要保存的行在控制器中形成正确的结构。【参考方案2】:
public function add_staff_attendance($data)

    $this->db->trans_begin();
    foreach ($data['total_present_day'] as $key => $value) 
        
            $dataToSave = array(
                'year' => $data['year'], // this seems to be same for all
                'month' => $data['month'], // this seems to be same for all
                'type_id' => $value['salary_type'][$key], // please change name='salary_type[]' in your form  
                'total_present' => $value['total_present_day'][$key], // seems to be an array
                'absent' => $value['total_absent_day'][$key],  // seems to be an array
                'memo' => $value['memo'][$key], // seems to be an array
                'staf_id' => $value['staff_id'][$key] // seems to be an array
            );
            $this->db->insert('staff_attendance', $dataToSave);
        
        if ($this->db->trans_status() === false) 
            $this->db->trans_rollback();
            return false;
         else 
            $this->db->trans_commit();
            return true;
        
    

【讨论】:

它解决了错误,但是除了年和月之外的所有值都返回一个空值 我已经更新了答案。请检查这个。为了方便起见,我已经发表了评论。 现在插入数据,年月值正确,其他列插入2,不正确 能否请您在插入前转储 $dataToSave 并分享结果。 这是结果数组 ( [year] => 1400 [month] => 1 [type_id] => 2 [total_present] => 2 [absent] => 2 [memo] => 2 [staf_id] => 2 ) 我不知道为什么值是 2【参考方案3】:

我通过更改控制器和模型中的一些代码解决了我的问题。 控制器:

public function store_attendance()
   
    $data = array();
    $insert_att = 0;
    $tst = $this->input->post('total_present_day');

    for ($i=0; $i < count($tst); $i++) 
      
        $data = array(
            'year' =>  $this->input->post('year'),
            'month' => $this->input->post('month'),
            'staf_id' => $this->input->post('staff_id')[$i],
            'total_present' => $this->input->post('total_present_day')[$i],
            'absent'=>$this->input->post('total_absent_day')[$i],
            'type_id'=>$this->input->post('salary_type')[$i],
            'memo'=>$this->input->post('memo')[$i],
        );
        // var_dump($data);
        
        $this->get_public_data->saveData('staff_attendance', $data);
        
    

    echo redirect(base_url().'hr/home/rgisterAttendance');

型号:

 public function add_staff_attendance($data)
  
  $this->db->insert('staff_attendance', $data);      

【讨论】:

围绕单个/单个插入方法使用事务是没有意义的。当您因为失败而回滚时,您只会回滚一行,并且该批次将被部分保存。因此,删除所有trans_ 调用将具有相同的效果。提交完全成功或没有保存行对您的应用程序是否重要?或者批次插入部分成功是否可以接受?我将假设部分保存的提交将是一件坏事。 在每次迭代中调用count() 是不必要的——因为计数永远不会改变。你为什么要echoredirect()?你会注意到 CodeIgniter 特意创建了一个方法来适应多行数据的插入——insert_batch()【参考方案4】:

看来是控制器出错了,保存的时候一定要遍历数组。

public function store_attendance()

    $data=array(

        'year' =>  $this->input->post('year'),
        'month' => $this->input->post('month'),
        'staff_id' => $this->input->post('staff_id'),
        'total_present_day' => $this->input->post('total_present_day'),
        'total_absent_day'=>$this->input->post('total_absent_day'),
        'salary_type'=>$this->input->post('salary_type'),
        'memo'=>$this->input->post('memo')
    );
    foreach($data as $d):
   
    $insert_att = $this->stuff_model->add_staff_attendance($d);
    
    if($insert_att)
    
        echo redirect(base_url().'hr/register_employee_attendance');
    
    else
    
        echo redirect(base_url().'hr/register_employee_attendance');
    
    endforeach;

你应该试试类似的东西

【讨论】:

不能将数组数据保存在一行的列中。

以上是关于如何在 Codeigniter 中的数据库中插入数组?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 codeigniter 中的事务进行基于数据更改的提交和回滚?

如何使用codeigniter 4框架在mysql数据库中插入多行?

如何在 Codeigniter 中插入动态数据?

如何使用 CodeIgniter 在数据库中插入多个值?

如何在codeigniter中使用ajax在mysql数据库中插入数据?

数据库中的值未插入codeIgniter?