Codeigniter表库处理空/空值

时间:2019-02-28 16:46:42

标签: php arrays codeigniter foreach codeigniter-3

我正在使用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

我该如何实现?

1 个答案:

答案 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
    //...
)
 ....

Sandbox

我将这些内容分开放置,以便于阅读,但没有理由您不能这样做。

//...
$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)));

Sandbox

我不得不猜测最终结果是什么,所以我运行了您的原始代码,它给了我:

Array
(
    [0] => Array
        (
            [data] => <strong>ID</strong>
        )

    [1] => 102
    //[2] => 108
    //...
)
....

在我的代码中,您可以用此调用print_r替换$this->table->add_row([..array data..]);array dataprint_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中的多余数据被删除。这有利于向前兼容。
  • (一旦您知道它是如何工作的),它的含义就容易多了,因为“瞬态”变量更少,并且对键ect的摆弄也更少了。

基本上,我的工作是控制原始代码中的$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
)

Sandbox (Orignal Code)

尽管这些事情可能永远不会导致问题,但它突出了我的观点,即基于$headings而不是$tableData的输出。事情往往会发生变化,这样,如果您从此数据中添加/删除字段,则不必担心它会破坏此页面等。

array_fill_keysarray_intersect_keyarray_merge的组合可用于将一个数组的标头(如上所示)映射到另一个数组。您可以使用array_combine($headings, $row)物理地交换它们,您将得到如下内容:

[
     [
         '<strong>ID</strong>' => 102,
         '<strong>First Name</strong>' => 'Ross',
          //...
     ],
     [...]
]

它非常适合CSV文件(这是我想出来的)以及您需要重新映射其键的其他任何内容。

无论如何,希望对您有帮助!