PHP已经提供了99,9%的需求,您可以通过扩展来添加缺少的0,1%。在下面的示例中,从它扩展:SplFileObject
CSVFile
$csv = new CSVFile('../data/test.csv');
foreach ($csv as $line)
{
var_dump($line);
}
使用您的示例数据:
array(3) {
["Make"]=> string(5) "Chevy"
["Model"]=> string(4) "1500"
["Note"]=> string(6) "loaded"
}
array(3) {
["Make"]=> string(5) "Chevy"
["Model"]=> string(4) "2500"
["Note"]=> string(0) ""
}
array(3) {
["Make"]=> string(5) "Chevy"
["Model"]=> string(0) ""
["Note"]=> string(6) "loaded"
}
CSVFile
定义如下:
class CSVFile extends SplFileObject
{
private $keys;
public function __construct($file)
{
parent::__construct($file);
$this->setFlags(SplFileObject::READ_CSV);
}
public function rewind()
{
parent::rewind();
$this->keys = parent::current();
parent::next();
}
public function current()
{
return array_combine($this->keys, parent::current());
}
public function getKeys()
{
return $this->keys;
}
}
如果你这样做,细节就会被很好地封装起来。此外,处理函数内部的错误(例如计数不匹配)更容易,因此使用数据的代码不需要处理它。current()
编辑:
然而,给出的例子在可重用性方面很短。与其从SplFileObject扩展,不如聚合它:
class KeyedArrayIterator extends IteratorIterator
{
private $keys;
public function rewind()
{
parent::rewind();
$this->keys = parent::current();
parent::next();
}
public function current()
{
return array_combine($this->keys, parent::current());
}
public function getKeys()
{
return $this->keys;
}
}
代码是相同的,但省略了构造函数中封装的详细信息。这种减少允许更广泛地使用该类型,例如,与(但不仅仅是)所述SplFileObject:
$file = new SplFileObject('../data/test.csv');
$file->setFlags($file::READ_CSV);
$csv = new KeyedArrayIterator($file);
foreach ($csv as $line) {
var_dump($line);
}
如果现在听起来太冗长,那么可以再次包装它以再次给它一个更好的外观:
class CSVFile extends KeyedArrayIterator
{
/**
* @param string $file
*/
public function __construct($file)
{
parent::__construct(new SplFileObject($file));
$this->setFlags(SplFileObject::READ_CSV);
}
}
由于TraversableIterator的标准修饰能力,CSVFile的第一个示例中的原始构造函数代码可以100%复制。
最后一个添加还允许保持使用 CSVFile 迭代器的原始代码不变:
$csv = new CSVFile('../data/test.csv');
foreach ($csv as $line) {
var_dump($line);
}
因此,只需快速重构即可实现更多的代码重用。您可以免费获得一个KeyedArrayIterator。