PHP-按列排列为CSV [英] PHP - Array to CSV by Column

查看:74
本文介绍了PHP-按列排列为CSV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:我有一个关联数组,其中所有键代表csv标头,每个$ key =>数组中的值..代表该列中的项目.

issue: I have an associative array, where all the keys represent the csv headers and the values in each $key => array.. represent the items in that column.

研究:据我所知, fputcsv 喜欢逐行浏览,但是这种基于列的数组使事情变得复杂.我还没有找到完成此功能的功能.

Research: To my knowledge, fputcsv likes to go in row by row, but this column-based array is making that complicated. I have not found any function out there that accomplishes this.

示例:

Array(
    ['fruits'] => Array(
        [0] => 'apples',
        [1] => 'oranges',
        [2] => 'bananas'
    ),
    ['meats'] => Array(
        [0] => 'porkchop',
        [1] => 'chicken',
        [2] => 'salami',
        [3] => 'rabbit'
    ),
)

需要成为:

fruits,meats
apples,porkchop
oranges,chicken
bananas,salami
,rabbit

为什么很难:

您需要知道空白行的最大行数.

You need to know the max number of rows to make blank spots.

推荐答案

我必须编写自己的函数.以为也许会对别人有帮助!

I had to write my own function. Thought maybe it might help someone else!

/*
 * The array is associative, where the keys are headers
 * and the values are the items in that column.
 * 
 * Because the array is by column, this function is probably costly.
 * Consider a different layout for your array and use a better function.
 * 
 * @param $array array The array to convert to csv.
 * @param $file string of the path to write the file.
 * @param $delimeter string a character to act as glue.
 * @param $enclosure string a character to wrap around text that contains the delimeter
 * @param $escape string a character to escape the enclosure character.
 * @return mixed int|boolean result of file_put_contents.
 */

function array_to_csv($array, $file, $delimeter = ',', $enclosure = '"', $escape = '\\'){
    $max_rows = get_max_array_values($array);
    $row_array = array();
    $content = '';
    foreach ($array as $header => $values) {
    $row_array[0][] = $header;
    $count = count($values);
    for ($c = 1; $c <= $count; $c++){
        $value = $values[$c - 1];
        $value = preg_replace('#"#', $escape.'"', $value);
        $put_value = (preg_match("#$delimeter#", $value)) ? $enclosure.$value.$enclosure : $value;
        $row_array[$c][] = $put_value;
    }
    // catch extra rows that need to be blank
    for (; $c <= $max_rows; $c++) {
        $row_array[$c][] = '';
    }
    }
    foreach ($row_array as $cur_row) {
    $content .= implode($delimeter,$cur_row)."\n";
    }
    return file_put_contents($file, $content);
}

这:

/*
 * Get maximum number of values in the entire array.
 */
function get_max_array_values($array){
    $max_rows = 0;
    foreach ($array as $cur_array) {
    $cur_count = count($cur_array);
    $max_rows = ($max_rows < $cur_count) ? $cur_count : $max_rows;
    }
    return $max_rows;
}


新方法(使用课程)

稍后我为此编写了一个课程,该课程将提供给现在正在寻找它的任何人:


New Way (using a class)

I wrote a class for this a while later, which I'll provide for anyone looking for one now:

class CSVService {

    protected $csvSyntax;

    public function __construct()
    {
        return $this;
    }

    public function renderCSV($contents, $filename = 'data.csv')
    {
        header('Content-type: text/csv');
        header('Content-Disposition: attachment; filename="' . $filename . '"');

        echo $contents;
    }

    public function CSVtoArray($filename = '', $delimiter = ',') {
        if (!file_exists($filename) || !is_readable($filename)) {
            return false;
        }

        $headers = null;
        $data = array();
        if (($handle = fopen($filename, 'r')) !== false) {
            while (($row = fgetcsv($handle, 0, $delimiter, '"')) !== false) {
                if (!$headers) {
                    $headers = $row;
                    array_walk($headers, 'trim');
                    $headers = array_unique($headers);
                } else {
                    for ($i = 0, $j = count($headers); $i < $j;  ++$i) {
                        $row[$i] = trim($row[$i]);
                        if (empty($row[$i]) && !isset($data[trim($headers[$i])])) {
                            $data[trim($headers[$i])] = array();
                        } else if (empty($row[$i])) {
                            continue;
                        } else {
                            $data[trim($headers[$i])][] = stripcslashes($row[$i]);
                        }
                    }
                }
            }
            fclose($handle);
        }
        return $data;
    }

    protected function getMaxArrayValues($array)
    {
        return array_reduce($array, function($carry, $item){
            return ($carry > $c = count($item)) ? $carry : $c;
        }, 0);
    }

    private function getCSVHeaders($array)
    {
        return array_reduce(
                array_keys($array),
                function($carry, $item) {
                    return $carry . $this->prepareCSVValue($item) . $this->csvSyntax->delimiter;
                }, '') . "\n";
    }

    private function prepareCSVValue($value, $delimiter = ',', $enclosure = '"', $escape = '\\')
    {
        $valueEscaped = preg_replace('#"#', $escape . '"', $value);
        return (preg_match("#$delimiter#", $valueEscaped)) ?
                $enclosure . $valueEscaped . $enclosure : $valueEscaped;
    }

    private function setUpCSVSyntax($delimiter, $enclosure, $escape)
    {
        $this->csvSyntax = (object) [
            'delimiter' => $delimiter,
            'enclosure' => $enclosure,
            'escape'    => $escape,
        ];
    }

    private function getCSVRows($array)
    {
        $n = $this->getMaxArrayValues($array);
        $even = array_values(
            array_map(function($columnArray) use ($n) {
                for ($i = count($columnArray); $i <= $n; $i++) {
                    $columnArray[] = '';
                }
                return $columnArray;
            }, $array)
        );

        $rowString = '';

        for ($row = 0; $row < $n; $row++) {
            for ($col = 0; $col < count($even); $col++) {
                $value = $even[$col][$row];
                $rowString .=
                        $this->prepareCSVValue($value) .
                        $this->csvSyntax->delimiter;
            }
            $rowString .= "\n";
        }

        return $rowString;
    }

    public function arrayToCSV($array, $delimiter = ',', $enclosure = '"', $escape = '\\', $headers = true) {
        $this->setUpCSVSyntax($delimiter, $enclosure, $escape);

        $headersString = ($headers) ? $this->getCSVHeaders($array) : '';

        $rowsString = $this->getCSVRows($array);


        return $headersString . $rowsString;
    }

}

这篇关于PHP-按列排列为CSV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆