处理来自textarea的多行数据;更有效的方式?

时间:2011-11-25 19:30:45

标签: php arrays foreach

在我的应用中,我有一个textarea,我的用户打算以下列格式输入数据:

Forename, Surname, YYYY-MM-DD, Company
Forename, Surname, YYYY-MM-DD, Company
每行

。我的意图是循环遍历每一行,用逗号爆炸并修剪任何空白区域。

然后我需要将展开的数组传递给关联数组。我假设用户已按照正确的顺序和格式输入数据,此时我手动执行此操作;哪个确实有效,但确实依赖于用户不会弄乱的东西。

你会建议做什么更好的方法?我认为我检查每个索引以查看它是否为空的方式看起来相当笨重,而且容易出错。

要考虑的任何建议或事项?

/************************************
* sample data from textarea:
* Name, Surname, 1980-02-22, Company
* Foo, Bar, 1970-05-12, Baz
************************************/
$data = preg_split('/\r\n|\n/', $_POST['data'], 
                                     -1,  PREG_SPLIT_NO_EMPTY);

$item = array();                
// loop through the data            
foreach($data as $row) :
    //  trim and explode each line in to an array
     $item[] = array_map('trim', explode(',', $row));
endforeach;

$k=0;
foreach($item as $user) :

    $processed_data[$k]['first_name'] = !empty($user[0]) ? $user[0] : NULL;
    $processed_data[$k]['last_name'] = !empty($user[1]) ? $user[1] : NULL;

    if(!empty($user[2])) :
        $dob = strtotime($user[2]);
        if($dob) {
            $processed_data[$k]['dob'] = $user[2];
        } else {
            $processed_data[$k]['dob'] = NULL;  
        }
    else:
        $processed_data[$k]['dob'] = NULL;  
    endif;

    $processed_data[$k]['company'] = !empty($user[3]) ? $user[3] : NULL;
    $k++;

endforeach;

// print_r($processed_data);

2 个答案:

答案 0 :(得分:0)

你来自旧学校:) 好吧,如上所述,您希望用户在文本区域中正确输入数据。好吧,如果你的应用目前在一个强大的系统中工作,请不要触摸它,否则你应该考虑在你的帖子请求中添加不同的参数(每个你想要爆炸的文件一个)......

你可以这样做来解决你现在遇到的问题:

// The algorithm below believe user send data correctly
// Forename, Surname, YYYY-MM-DD, Company
$names = array('first_name', 'last_name', 'dob', 'company_name');

$lines = explode("\n", $_POST['data']);

$result = array();
foreach ($lines as $ line)
{
   $exploded_line = explode(",", $line);
   $row = array();
   foreach ($exploded_line as $key=>$item) { $row[$names[$key]]= trim($item); }
   $result[]=$row;
}

// Now in result there is an array like this
// result[0][first_name]
// result[0][last_name]
// result[0][dob]
// result[0][company_name]
// result[1][first_name]
// [ ... ]

答案 1 :(得分:0)

您可以将解析和验证封装到自己的类中。此外,您可以对包含表格数据的数据结构执行相同的操作。

class TableParser
{
    private $string;
    public function __construct($string)
    {
        $this->string = (string) $string;
    }
    public function parse()
    {
        $buffer = $this->string;
        $rows = explode("\n", $buffer);
        $rows = array_map('trim', $rows);
        return $this->parseRows($rows);
    }
    private function parseRows(array $rows)
    {
        foreach($rows as &$row)
        {
            $row = $this->parseRow($row);   
        }
        return $rows;
    }
    private function parseRow($row)
    {
        $keys = array('forename', 'surname', 'date', 'company');
        $keyCount = count($keys)
        $row = explode(',', $row, $keyCount);
        if (count($row) != $keyCount)
        {
            throw new InvalidArgumentException('A row must have 4 columns.');
        }
        $row = array_map('trim', $row);
        $row = array_combine($keys, $row);
        return $row;
    }
}

这个解析器仍然非常粗糙。您可以随着时间的推移改进它,例如提供更好的错误处理,给出哪些线路失败的信息等。这样的组件可以更容易地集成到您的正常应用程序流中,因为您可以将该信息返回给用户,以便她能够对输入进行更改。

此外,您可以将验证分解为第二个类,并且仅在解析器中进行爆炸/修剪,但是对计数进行验证,指定数组键以及验证第二个类中的日期格式/值以保留事物更加分开。