PHP ofrece ya el 99,9% de lo que necesita dentro de SplFileObject
, se agrega la falta 0,1% mediante la extensión de la misma. En el siguiente ejemplo CSVFile
se extiende desde ella:
$csv = new CSVFile('../data/test.csv');
foreach ($csv as $line)
{
var_dump($line);
}
Con los datos del ejemplo:
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
se define como la siguiente:
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;
}
}
Si lo haces de esta manera, el los detalles están muy bien encapsulados. Además, es más fácil tratar los errores (por ejemplo, desajuste de cuenta) dentro de la función current()
, por lo que el código que hace uso de los datos no necesita tratar con él.
Editar:
Sin embargo, el ejemplo dado es corto en términos de re-usablity. En lugar de que se extiende desde SplFileObject que es mucho mejor para agregarla:
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;
}
}
El código es idéntico pero los detalles que fueron encapsulados en el constructor se quedan fuera. Esta reducción permite usar el tipo de manera más amplia, p.con (pero no sólo con) el dijo SplFileObject:
$file = new SplFileObject('../data/test.csv');
$file->setFlags($file::READ_CSV);
$csv = new KeyedArrayIterator($file);
foreach ($csv as $line) {
var_dump($line);
}
Si eso ahora suena demasiado prolijo, de nuevo se puede envolver para dar de nuevo una fachada más bonita:
class CSVFile extends KeyedArrayIterator
{
/**
* @param string $file
*/
public function __construct($file)
{
parent::__construct(new SplFileObject($file));
$this->setFlags(SplFileObject::READ_CSV);
}
}
Gracias a la capacidad de decoración estándar de TraversableIterator, el código de constructor original del primer ejemplo de CSVFile podría copiarse solo al 100%.
Este último además también permite mantener el código original que utiliza la CSVFile iterador intacta:
$csv = new CSVFile('../data/test.csv');
foreach ($csv as $line) {
var_dump($line);
}
lo tanto, sólo una refactorización rápida para permitir una mayor reutilización de códigos. Obtiene un KeyedArrayIterator de forma gratuita.
probablemente significará 2500 en el segundo ejemplo de matriz – user1899415