Memoria PHP exhausta al usar array_combine en foreach loop

Tengo problemas cuando intenté usar array_combine en un ciclo foreach . Terminará con un error:

 PHP Fatal error: Allowed memory size of 268435456 bytes exhausted (tried to allocate 85 bytes) in 

Aquí está mi código:

 $data = array(); $csvData = $this->getData($file); if ($columnNames) { $columns = array_shift($csvData); foreach ($csvData as $keyIndex => $rowData) { $data[$keyIndex] = array_combine($columns, array_values($rowData)); } } return $data; 

El archivo fuente CSV que he usado tiene aproximadamente ~ 1,000,000 de filas. Esta fila

 $csvData = $this->getData($file) 

Estaba usando un ciclo while para leer CSV y asignarlo a una matriz, está funcionando sin ningún problema. El problema proviene de array_combine y foreach loop.

¿Tiene alguna idea para resolver esto o simplemente tener una mejor solución?

ACTUALIZADO

Aquí está el código para leer el archivo CSV (usando while loop)

 $data = array(); if (!file_exists($file)) { throw new Exception('File "' . $file . '" do not exists'); } $fh = fopen($file, 'r'); while ($rowData = fgetcsv($fh, $this->_lineLength, $this->_delimiter, $this->_enclosure)) { $data[] = $rowData; } fclose($fh); return $data; 

ACTUALIZADO 2

El código anterior funciona sin problemas si estás jugando con un archivo CSV <= 20,000 ~ 30,000 filas. Desde 50,000 filas hacia arriba, la memoria se agotará.

De hecho, conserva (o intenta mantener) dos copias distintas de todo el conjunto de datos en su memoria. Primero carga la fecha completa de CSV en la memoria usando getData() y copia los datos en la matriz de $data haciendo un bucle sobre los datos en la memoria y creando una nueva matriz.

Debe usar la lectura basada en flujo al cargar los datos CSV para mantener solo un conjunto de datos en la memoria. Si tienes PHP 5.5+ (que por cierto deberías tener), esto es tan simple como cambiar tu método getData para que se vea así:

 protected function getData($file) { if (!file_exists($file)) { throw new Exception('File "' . $file . '" do not exists'); } $fh = fopen($file, 'r'); while ($rowData = fgetcsv($fh, $this->_lineLength, $this->_delimiter, $this->_enclosure)) { yield $rowData; } fclose($fh); } 

Esto hace uso de un llamado generador que es una función de PHP> = 5.5. El rest de su código debe seguir funcionando ya que el funcionamiento interno de getData debe ser transparente para el código de llamada (solo la mitad de la verdad).

ACTUALIZA para explicar cómo funcionará la extracción de los encabezados de columna.

 $data = array(); $csvData = $this->getData($file); if ($columnNames) { // don't know what this one does exactly $columns = null; foreach ($csvData as $keyIndex => $rowData) { if ($keyIndex === 0) { $columns = $rowData; } else { $data[$keyIndex/* -1 if you need 0-index */] = array_combine( $columns, array_values($rowData) ); } } } return $data;