fputcsv() quotes a field only when needed and doubles embedded quotes, as RFC 4180 requires; fgetcsv() and str_getcsv() parse it back. All three take an $escape character, a PHP-only extra whose default "\\" breaks round trips. Since PHP 8.4 omitting it is deprecated (the default changes in PHP 9.0 at the earliest), so pass '':
<?php
declare(strict_types=1);
error_reporting(E_ALL); // Ubuntu hides E_DEPRECATED
foreach (['\\', ''] as $esc) {
$fp = fopen('php://memory', 'r+'); // an in-memory file (Section 4.8.7)
fputcsv($fp, ['BK-101', 'Dune, "Deluxe"', 'C:\\'], ',', '"', $esc);
fputcsv($fp, ['BK-205', 'Emma', '/'], ',', '"', $esc);
rewind($fp);
echo json_encode($esc), ' ', json_encode(fgetcsv($fp, null, ',', '"', $esc)), "\n";
}
str_getcsv('a,b'); // relies on the default
$ini = "[db]\nport = 3306\ndebug = off\n[mail]\nfrom = \"shop@example.com\"\n";
echo json_encode(parse_ini_string($ini, true, INI_SCANNER_TYPED)), "\n";
echo json_encode(unpack('A6sku/x/A12title/A6price', 'BK-101 Dune 9.99 ')), "\n";"\\" ["BK-101","Dune, \"Deluxe\"","C:\\\"\nBK-205,Emma,\/\n"]
"" ["BK-101","Dune, \"Deluxe\"","C:\\"]
PHP Deprecated: str_getcsv(): the $escape parameter must be provided as its default value
will change in /home/dev/shop/main.php on line 11
{"db":{"port":3306,"debug":false},"mail":{"from":"shop@example.com"}}
{"sku":"BK-101","title":"Dune","price":"9.99"}With "\\", the quote after C:\ reads as escaped, so the field swallows the next row; with '' both rows survive. SplFileObject reads CSV in a foreach with READ_CSV and setCsvControl(',', '"', ''). INI_SCANNER_TYPED yields real integers and booleans, and unpack() A fields strip fixed-width padding. For large imports, use league/csv 3,483 (https://github.com/thephpleague/csv 3,483 ) (composer require league/csv, 9.28.0).