处理来自文本区的多行数据;更有效的方法


Processing multiple lines of data from a textarea; more efficient way?

在我的应用程序中,我有一个文本区,我的用户意味着输入数据的格式:

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);

你是老派的。正如上面所说,您希望用户在文本区域中正确输入数据。好吧,如果你的应用目前运行在一个健壮的系统中,不要碰它,否则你应该考虑在你的post request中添加不同的参数(一个你想要爆炸的文件)…

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

// 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]
// [ ... ]

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

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;
    }
}

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

此外,您可以将验证分离到第二个类中,只在解析器中执行爆炸/修剪,但根据计数进行验证,指定数组键以及在第二个类中验证日期格式/值,以使事情更加分开。