@@ -62,8 +62,19 @@ class Csv extends BaseReader
6262
6363 /**
6464 * The character that can escape the enclosure.
65+ * This will probably become unsupported in Php 9.
66+ * Not yet ready to mark deprecated in order to give users
67+ * a migration path.
6568 */
66- private string $ escapeCharacter = '\\' ;
69+ private ?string $ escapeCharacter = null ;
70+
71+ /**
72+ * The character that will be supplied to fgetcsv
73+ * when escapeCharacter is null.
74+ * It is anticipated that it will conditionally be set
75+ * to null-string for Php9 and above.
76+ */
77+ private static string $ defaultEscapeCharacter = '\\' ;
6778
6879 /**
6980 * Callback for setting defaults in construction.
@@ -185,7 +196,7 @@ protected function inferSeparator(): void
185196 return ;
186197 }
187198
188- $ inferenceEngine = new Delimiter ($ this ->fileHandle , $ this ->escapeCharacter , $ this ->enclosure );
199+ $ inferenceEngine = new Delimiter ($ this ->fileHandle , $ this ->escapeCharacter ?? self :: $ defaultEscapeCharacter , $ this ->enclosure );
189200
190201 // If number of lines is 0, nothing to infer : fall back to the default
191202 if ($ inferenceEngine ->linesCounted () === 0 ) {
@@ -228,11 +239,11 @@ public function listWorksheetInfo(string $filename): array
228239 $ delimiter = $ this ->delimiter ?? '' ;
229240
230241 // Loop through each line of the file in turn
231- $ rowData = fgetcsv ($ fileHandle , 0 , $ delimiter , $ this ->enclosure , $ this ->escapeCharacter );
242+ $ rowData = self :: getCsv ($ fileHandle , 0 , $ delimiter , $ this ->enclosure , $ this ->escapeCharacter );
232243 while (is_array ($ rowData )) {
233244 ++$ worksheetInfo [0 ]['totalRows ' ];
234245 $ worksheetInfo [0 ]['lastColumnIndex ' ] = max ($ worksheetInfo [0 ]['lastColumnIndex ' ], count ($ rowData ) - 1 );
235- $ rowData = fgetcsv ($ fileHandle , 0 , $ delimiter , $ this ->enclosure , $ this ->escapeCharacter );
246+ $ rowData = self :: getCsv ($ fileHandle , 0 , $ delimiter , $ this ->enclosure , $ this ->escapeCharacter );
236247 }
237248
238249 $ worksheetInfo [0 ]['lastColumnLetter ' ] = Coordinate::stringFromColumnIndex ($ worksheetInfo [0 ]['lastColumnIndex ' ] + 1 );
@@ -379,7 +390,7 @@ private function loadStringOrFile(string $filename, Spreadsheet $spreadsheet, bo
379390
380391 // Loop through each line of the file in turn
381392 $ delimiter = $ this ->delimiter ?? '' ;
382- $ rowData = fgetcsv ($ fileHandle , 0 , $ delimiter , $ this ->enclosure , $ this ->escapeCharacter );
393+ $ rowData = self :: getCsv ($ fileHandle , 0 , $ delimiter , $ this ->enclosure , $ this ->escapeCharacter );
383394 $ valueBinder = Cell::getValueBinder ();
384395 $ preserveBooleanString = method_exists ($ valueBinder , 'getBooleanConversion ' ) && $ valueBinder ->getBooleanConversion ();
385396 $ this ->getTrue = Calculation::getTRUE ();
@@ -416,7 +427,7 @@ private function loadStringOrFile(string $filename, Spreadsheet $spreadsheet, bo
416427 }
417428 ++$ columnLetter ;
418429 }
419- $ rowData = fgetcsv ($ fileHandle , 0 , $ delimiter , $ this ->enclosure , $ this ->escapeCharacter );
430+ $ rowData = self :: getCsv ($ fileHandle , 0 , $ delimiter , $ this ->enclosure , $ this ->escapeCharacter );
420431 ++$ currentRow ;
421432 }
422433
@@ -527,6 +538,11 @@ public function getContiguous(): bool
527538 return $ this ->contiguous ;
528539 }
529540
541+ /**
542+ * Php9 intends to drop support for this parameter in fgetcsv.
543+ * Not yet ready to mark deprecated in order to give users
544+ * a migration path.
545+ */
530546 public function setEscapeCharacter (string $ escapeCharacter ): self
531547 {
532548 $ this ->escapeCharacter = $ escapeCharacter ;
@@ -536,7 +552,7 @@ public function setEscapeCharacter(string $escapeCharacter): self
536552
537553 public function getEscapeCharacter (): string
538554 {
539- return $ this ->escapeCharacter ;
555+ return $ this ->escapeCharacter ?? self :: $ defaultEscapeCharacter ;
540556 }
541557
542558 /**
@@ -649,4 +665,28 @@ public function setSheetNameIsFileName(bool $sheetNameIsFileName): self
649665
650666 return $ this ;
651667 }
668+
669+ /**
670+ * Php8.4 deprecates use of anything other than null string
671+ * as escape Character.
672+ *
673+ * @param resource $stream
674+ * @param null|int<0, max> $length
675+ *
676+ * @return array<int,?string>|false
677+ */
678+ private static function getCsv (
679+ $ stream ,
680+ ?int $ length = null ,
681+ string $ separator = ', ' ,
682+ string $ enclosure = '" ' ,
683+ ?string $ escape = null
684+ ): array |false {
685+ $ escape = $ escape ?? self ::$ defaultEscapeCharacter ;
686+ if (PHP_VERSION_ID >= 80400 && $ escape !== '' ) {
687+ return @fgetcsv ($ stream , $ length , $ separator , $ enclosure , $ escape );
688+ }
689+
690+ return fgetcsv ($ stream , $ length , $ separator , $ enclosure , $ escape );
691+ }
652692}
0 commit comments