我正在使用Codeigniter 3和table library,以便以以下格式显示一些数据;
+---------------+---------------------+
| id | 102 |
+---------------+---------------------+
| First Name | Ross |
+---------------+---------------------+
| Last Name | Bing |
+---------------+---------------------+
| Title | Doctor |
+---------------+---------------------+
| Timestamp | 2019-01-18 10:17:05 |
+---------------+---------------------+
| Member Number | |
+---------------+---------------------+
$tableData
的书信是;
Array
(
[0] => Array
(
[id] => 102
[firstname] => Ross
[lastname] => Bing
[title] => Doctor
[timestamp] => 2019-01-18 10:17:05
[member_no] =>
)
)
我用来生成HTML表的PHP代码是;
$tableData = $this->My_model->getData();
$heading = array(
'id' => 'ID',
'firstname' => 'First Name',
'lastname' => 'Last Name',
'title' => 'Title',
'timestamp' => 'Date Submitted',
'member_no' => 'Member Number'
);
$fields = array_keys($tableData[0]);
$rows = array();
foreach($fields as $key => $field) {
$rows[$key][0] = array(
'data' => '<strong>' . $heading[$field] . '</strong>'
);
foreach($tableData as $key2 => $item) {
$rows[$key][$key2 + 1] = $item[$field];
}
}
foreach($rows as $row) {
$this->table->add_row($row);
}
上面的代码可以正常工作,但是,如果一行为空(请参见上面的member_no
),我想做两件事之一(以最简单的为准);
not available
我该如何实现?
答案 0 :(得分:2)
我会做这样的事情:
$tableData = array (
0 =>
array (
'id' => 102,
'lastname' => 'Bing',
'title' => 'Doctor',
'timestamp' => '2019-01-1810:17:05',
'member_no' => null,
'firstname' => 'Ross', //intentionally moved to show ordering
'foobar' => 'blah' //added for example, this will be removed by array_intersect_key
),
);
$heading = array(
'id' => '<strong>ID</strong>',
'firstname' => '<strong>First Name</strong>',
'lastname' => '<strong>Last Name</strong>',
'title' => '<strong>Title</strong>',
'timestamp' => '<strong>Date Submitted</strong>',
'member_no' => '<strong>Member Number</strong>'
);
//create a default array
//this takes the keys from $heading, and makes an array with all the values as 'not available'
// ['id' => 'not available','lastname' => 'not available', ... ]
$default = array_fill_keys(array_keys($heading), 'not available');
$rows = [];
foreach($tableData as $key => $row) {
//remove all elements with strlen of 0 (in this case 'member_no')
$row = array_filter($row, function($item){return strlen($item);});
//removes 'foobar' or anything that has a key not in $heading
$row = array_intersect_key($row, $heading);
//combine $default and $data (empty items in $row are filled in from default)
//such as items removed by array_filter above
//the key order will match $default, which matches $headings
$row = array_merge($default, $row);
$rows[] = $row;
}
foreach($heading as $key=>$value) {
print_r(array_merge([['data'=>$value]], array_column($rows, $key)));
}
输出
Array
(
[0] => Array
(
[data] => <strong>ID</strong>
)
[1] => 102
//[2] => 108
//...
)
....
我将这些内容分开放置,以便于阅读,但没有理由您不能这样做。
//...
$default = array_fill_keys(array_keys($heading), 'not available');
foreach($tableData as $key => $row) $rows[] = array_merge($default, array_intersect_key(array_filter($row, function($item){return strlen($item);}), $heading));
foreach($heading as $key=>$value) print_r(array_merge([['data'=>$value]],array_column($rows, $key)));
我不得不猜测最终结果是什么,所以我运行了您的原始代码,它给了我:
Array
(
[0] => Array
(
[data] => <strong>ID</strong>
)
[1] => 102
//[2] => 108
//...
)
....
在我的代码中,您可以用此调用print_r
替换$this->table->add_row([..array data..]);
。 array data
是print_r
调用中的内容。您可以将其设置为变量,但是如果仅在此处使用该变量有什么用呢?这消除了一些循环(请参见下文)和其他一些优点:
$headings
的$headings
中的位置如何,元素都将在$tableData
数组中显示。举例来说,这也使数据的重新排列变得容易:您甚至可以将其映射到动态数组,我在CSV文件中执行此操作,从而允许用户更改标题和列的顺序。他们甚至可以重命名标头,因为key => value
配对的工作方式my_key => their_key
... $tableData
中丢失的数据默认为从not available
中提取的$default
,理论上您可以手动将其映射到其他事物。例如:您可以在使用$default['timestamp'] = date('Y-m-d H:i:s');
创建时间戳后立即将array_fill_keys
设置为当前时间的默认时间戳。$tableData
中未定义的$headings
中的多余数据被删除。这有利于向前兼容。基本上,我的工作是控制原始代码中的$headings
数组。您可以通过遍历键(fields
)来完成此操作,但这会使以后的$rows[$key][$key2 + 1]
变得更加复杂。如果数据在以后发生更改(例如向数据库添加新字段),则您可能会遇到未定义的数组索引问题。
输出的顺序取决于$tableData
中的数据,与依赖于$headings
的情况相比,该数据不那么直观(也不太有用)。
以下是原始代码中这些问题的示例:
//for example if your data changes to this and run your original code
$tableData = array (
0 =>
array (
'id' => 102,
'lastname' => 'Bing',
'title' => 'Doctor',
'timestamp' => '2019-01-1810:17:05',
'member_no' => null,
'firstname' => 'Ross', //intentionally moved to show ordering
'foo' => 'bar' //added this undefined in $headings
),
);
您将获得此通知,并发现最后2个元素是:
<br />
<b>Notice</b>: Undefined index: foo in <b>[...][...]</b> on line <b>30</b><br />
//... all other elements ...
//in orignal: displayed in the order of $tableData
//in my code: order is based on $headings, so this would be moved to the correct location
Array(
[0] => Array (
[data] => <strong>First Name</strong>
)
[1] => Ross
)
//in orignal: $headings['foo'] is not defined so we have no label here
//in my code: this element is removed and doesn't get rendered
Array(
[0] => Array(
[data] => <strong></strong>
)
[1] => bar
)
尽管这些事情可能永远不会导致问题,但它突出了我的观点,即基于$headings
而不是$tableData
的输出。事情往往会发生变化,这样,如果您从此数据中添加/删除字段,则不必担心它会破坏此页面等。
array_fill_keys
,array_intersect_key
和array_merge
的组合可用于将一个数组的标头(如上所示)映射到另一个数组。您可以使用array_combine($headings, $row)
物理地交换它们,您将得到如下内容:
[
[
'<strong>ID</strong>' => 102,
'<strong>First Name</strong>' => 'Ross',
//...
],
[...]
]
它非常适合CSV文件(这是我想出来的)以及您需要重新映射其键的其他任何内容。
无论如何,希望对您有帮助!