拆分 HTML <table> 和 CSV 的责任?

Split responsibilities for HTML <table> and CSV?

我想弄清楚什么是最好的方法来拆分 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;
}

我会创建一个类似于 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');