← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

PHP CSV Handling (fgetcsv / str_getcsv)

php PHP 5.3+ Beginner

Also Known As

fgetcsv str_getcsv fputcsv PHP CSV parser

TL;DR

PHP provides fgetcsv() for reading CSV line-by-line from a file handle and str_getcsv() for parsing a CSV string — both handle quoted fields, embedded commas, and escaped characters correctly where explode() does not.

Explanation

CSV parsing looks simple — split on commas — until you encounter quoted fields that contain commas, newlines inside quotes, or escaped quote characters. PHP's fgetcsv() reads one CSV row from an open file handle, correctly parsing all RFC 4180 quoting rules. str_getcsv() does the same for an in-memory string. For writing, fputcsv() formats an array as a CSV row with correct quoting. Key parameters: the delimiter (default comma), enclosure character (default double-quote), and escape character. In PHP 8.4, the escape parameter default changed — set it explicitly to avoid version-dependent behaviour. For large files, fgetcsv() in a loop with a generator avoids loading the entire file into memory.

Common Misconception

str_getcsv() can parse an entire multi-line CSV file. It parses a single CSV record (one logical row). Use fgetcsv() in a loop with an open file handle for multi-row files, or file() + array_map('str_getcsv') for small files already in memory.

Why It Matters

Naïve explode(',', $line) CSV parsing breaks on the first quoted field containing a comma — a common case in address fields, names, and any data with commas in it. Using the built-in functions handles all edge cases correctly and is faster than any pure-PHP alternative.

Common Mistakes

  • Not specifying escape: '' in PHP 8.4+ — the default escape character changed; explicitly set it to avoid version-dependent parsing differences.
  • Using file() + array_map('str_getcsv') on files with quoted newlines — file() splits on newlines, breaking multi-line quoted fields; only fgetcsv() handles embedded newlines correctly.
  • Forgetting to handle BOM (Byte Order Mark) on Windows-generated CSV files — strip the BOM from the first field: ltrim($firstField, "\xEF\xBB\xBF").
  • Not validating the number of fields per row — fgetcsv() returns arrays of varying length if rows have different field counts; always check count($row) === $expectedColumns.

Code Examples

✗ Vulnerable
<?php
// ❌ Naïve CSV parsing — breaks on quoted fields
$lines = file('data.csv');
foreach ($lines as $line) {
    $fields = explode(',', trim($line)); // Breaks on: "Smith, John",30,"New York, NY"
    processRow($fields);
}

// Also broken — loading entire large file into memory
$content = file_get_contents('huge_export.csv'); // 500MB in memory
$lines = explode("\n", $content);
✓ Fixed
<?php
// ✅ fgetcsv() — correct parsing, memory-efficient for large files
function readCsv(string $path): Generator
{
    $handle = fopen($path, 'r');
    if ($handle === false) throw new RuntimeException("Cannot open $path");

    $header = fgetcsv($handle); // First row is headers
    while (($row = fgetcsv($handle, escape: '')) !== false) {
        yield array_combine($header, $row);
    }
    fclose($handle);
}

foreach (readCsv('export.csv') as $row) {
    processRow($row); // One row in memory at a time
}

// Writing CSV
$handle = fopen('output.csv', 'w');
fputcsv($handle, ['name', 'email', 'city']); // Header
fputcsv($handle, ['Smith, John', 'john@example.com', 'New York, NY']);
fclose($handle);

Added 23 Mar 2026
Views 19
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 1 ping W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S
No pings yet today
No pings yesterday
Amazonbot 6 Google 4 Perplexity 2 ChatGPT 1 Ahrefs 1
crawler 13 crawler_json 1
DEV INTEL Tools & Severity
⚙ Fix effort: Low
⚡ Quick Fix
Replace explode(',', $line) with str_getcsv($line) for single lines, and replace file-reading loops with fgetcsv($handle) for large files.
📦 Applies To
PHP 5.3+ web cli

✓ schema.org compliant