Leer ficheros CSV enormes en PHP

Continúo con mi serie de posts sobre ficheros grandes. Tras descargar ficheros CSV enormes en local, me tocó leerlos y procesarlos. Imaginemos el siguiente código:

public function processFile(string $fileName)
{
	// descargamos el fichero con el método del post anterior
	$this->downloadFile($fileName);
    
	foreach ($this->rows($fileName) as $row) {
		$this->process($row);
	}
}

La clave está en este método rows. En este método, vamos a leer el fichero CSV línea a línea y vamos a ir devolviendo cada línea a través de un generator:

public function rows(string $fileName)
{
	$local = Storage::disk('local');
	$handle = fopen($local->path($fileName), 'r');
	$header = null;
	while (($line = fgets($handle)) !== false) {
		$row = str_getcsv($line, ";");
		if (is_null($header)) {
			$header = $row;
			continue;
		}

		$row = array_combine($header, $row);
		yield $row;
	}

	fclose($handle);
}

En este método hacemos lo siguiente:

  1. Inicializar el disco local
  2. Abrir el fichero $fileName en modo lectura con un puntero
  3. Comenzar a leer el fichero línea a línea
  4. La primera línea, la guardamos en la variable $header
  5. El resto de líneas las combinamos con el $header para tener un array asociativo
  6. Devolvemos cada fila, de una en una, a través de yield $row. Esto hará que no consumamos apenas memoria, ya que cada fila se procesa de una en una y no se van acumulando en memoria.
  7. Una vez terminamos, cerramos el fichero