Я бы сделал что-то вроде этого:
$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 (именно это я и понял) и всего остального, что вам нужно переназначитьключи для.
В любом случае, надеюсь, это поможет вам!