如何在 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->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 '<pre>'; print_r($data); echo '</pre>';
在模型中的结果:
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 因为不仅有员工要存储在数据库中,有时可能不止一个人 您知道,您的标记是无效的,因为您正在生成多个具有相同id
和sample_editable_2
的表。无论您使用 data="<?php echo $a;?>"
做什么,我都会将其删除,如果有必要,请找到更聪明的方法。
<?php if($st['memo']==null)echo '';else echo $st['memo'];?>
(和类似的重复代码)更简单地表示为<?php echo $st['memo'] ?: ''; ?>
...我不相信在这种情况下你甚至需要?: ''
。
如果控制器都指向同一个目的地,为什么会有条件重定向?
【参考方案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_insert
ion 的模型。
$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()
是不必要的——因为计数永远不会改变。你为什么要echo
redirect()
?你会注意到 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数据库中插入多行?