Обработка таблицы кодовых таблиц Пустые / пустые значения - PullRequest
0 голосов
/ 28 февраля 2019

Я использую Codeigniter 3 и библиотеку таблиц для отображения некоторых данных в следующем формате;

+---------------+---------------------+
| id            | 102                 |
+---------------+---------------------+
| First Name    | Ross                |
+---------------+---------------------+
| Last Name     | Bing                |
+---------------+---------------------+
| Title         | Doctor              |
+---------------+---------------------+
| Timestamp     | 2019-01-18 10:17:05 |
+---------------+---------------------+
| Member Number |                     |
+---------------+---------------------+

Vardump $tableData равен;

Array
(
    [0] => Array
        (
            [id] => 102
            [firstname] => Ross
            [lastname] => Bing
            [title] => Doctor
            [timestamp] => 2019-01-18 10:17:05
            [member_no] => 
        )
)

PHP-код, который я использую для генерации HTML-таблицы:

$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 в ячейке таблицы

Какя могу достичь этого?

1 Ответ

0 голосов
/ 28 февраля 2019

Я бы сделал что-то вроде этого:

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

В любом случае, надеюсь, это поможет вам!

...