【问题标题】:Split responsibilities for HTML <table> and CSV?拆分 HTML <table> 和 CSV 的职责?
【发布时间】:2015-07-10 17:04:32
【问题描述】:

我正在尝试找出将 HTML 视图和 CSV 的职责分开以进行导出(相同的视图数据)的最佳方法。当它几乎在做同样的事情时,我不想重复编写相同的 CSV 代码块。

下面的示例代码,首先从数据库中获取数据,然后将其处理成多维数组。你可以看到我使用了很多foreach 来生成报告。我是否对 CSV 导出重复此操作?必须有一个 DRY 解决方案。

下面的示例代码,您将如何划分 CSV 和 HTML 的职责?

function report($campaign, $agent, $startDate, $endDate) {

    $sql = "SELECT  count(*) as total, group_name, field, field, field, FROM table some ... inner joins table .. WHERE ... group by agent";

    $q = mysql_query($sql) or die(mysql_error());

    while($row = mysql_fetch_assoc($q)) {

        $report[ $row['group_name'] ][ $row['item'] ] ['total'] = 0;
        $report[ $row['group_name'] ][ $row['item'] ] ['total'] += $row['total'];
        $report[ $row['group_name'] ][ $row['item'] ] ['agent'][$row['agent']] = $row;

        if (!array_key_exists($row['agent'], $fieldsAgent)) {
            ..... 
        }
    }

    $html = "<table>";

    $html .= " <tr>";
    $html .= "   <td>Group</td>";
    $html .= "   <td>Item</td>";

    foreach($fieldsAgent as $agentCol => $agentTotal) {
        $html .= "<td>$agentCol</td>";
    }

    $html .= "  <td>Total</td>";
    $html .= "  </tr>";

    foreach ($report as $category => $items) {

        foreach($items as $itemName => $itemData) {

            $html .= "<tr>";
            $html .= " <td>" . $category . "</td>";
            $html .= " <td>" . $itemName . "</td>";

            foreach($fieldsAgent as $fieldAgentName => $totalAgentUser) {

                    $total = $itemData['agent'][ $fieldAgentName ][ 'total' ];
                    $html .= "<td>" . $total . "</td>";
            }

            $html .= " <td>" . $itemData['total'] . "</td>";
            $html .= "</tr>";
        } 
    }

    $html .= "</table>";

    echo $html;
}

【问题讨论】:

  • DRY 解决方案是将您的表示与数据逻辑分开,然后有两个单独的表示层(一个用于 html,另一个用于 csv)....这就是 MVC 的全部意义所在

标签: php dry


【解决方案1】:

我会创建一个类似tr_or_csv()的函数

function tr_or_csv($data = array(), $mode = 'csv')
{
    $result = '';

    if(is_array($data) && $data)
    {
        $mode = (is_string($mode) ? (in_array(strtolower($mode, array('csv','tr'))) ? $mode : 'csv') : 'csv');

        if($mode === csv)
        {
            $handle = fopen('php://temp', 'r+');
            fputcsv($handle, $data, ',');
            rewind($handle);
            while (!feof($handle))
            {
                $result.= fread($handle, 8192);
            }
            fclose($handle);
        }
        else
        {
            $result = '<tr><td>';
            $result.= implode('</td><td>', $data);
            $result.= '</td></tr>';
        }
    }

    return $result;
}

function report($campaign, $agent, $startDate, $endDate, $mode)
{
    // MySQL stuff, etc...

    $html.= tr_or_csv(array('Group','Item','Total'), $mode);

    // More code
}

report('new_campaign', 'Bob', '2015-01-01', '2015-07-10', 'tr');

【讨论】:

  • 我想我理解你所做的逻辑,非常有趣。您能想到替代解决方案吗?而不是为循环中的每一行执行tr_or_csv()。一个函数来获取数据并返回它,一个函数以 html 格式输出数据,一个函数以 csv 格式输出数据。例如:$output[]['column_name']='colum_value' 那么您可以通过接受数组或传递给 html 的 csv 函数将其格式化为 CSV?
  • @I'll-Be-Back 如果您了解我的代码,那么您为什么想不出解决方案?您基本上必须将我所做的事情分成两个功能。
  • @I'll-Be-Back 除了 DRY,还应该考虑 YAGNI 原则。
猜你喜欢
  • 2011-02-10
  • 1970-01-01
  • 1970-01-01
  • 2019-04-09
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多