Turn a CSV export into a PHP array in short [] syntax, ready to paste into a seeder, a config file or a test fixture. Numbers, booleans and nulls are written unquoted, so you do not have to fix types afterwards. Only values that look like JSON numbers are converted, so a ZIP code like 00501 stays the string "00501".
id,name,role,active
1,John Doe,Admin,true
2,Jane Smith,User,false [
[
'id' => 1,
'name' => 'John Doe',
'role' => 'Admin',
'active' => true
],
[
'id' => 2,
'name' => 'Jane Smith',
'role' => 'User',
'active' => false
]
] Convert a spreadsheet export once and paste the array into a database seeder or a PHPUnit data provider.
Commit the array when someone else maintains the list in a spreadsheet. Re-export and convert when it changes, and your code loads it with a plain require.
<?php
$csv = "sku,price,in_stock\nA-100,9.99,true\nB-200,15,false\n";
$handle = fopen('php://memory', 'r+');
fwrite($handle, $csv);
rewind($handle);
$headers = fgetcsv($handle, null, ',', '"', '\\');
$rows = [];
while (($line = fgetcsv($handle, null, ',', '"', '\\')) !== false) {
$rows[] = array_combine($headers, $line);
}
// Every value is a string; cast the columns you need
foreach ($rows as &$row) {
$row['price'] = (float) $row['price'];
$row['in_stock'] = filter_var($row['in_stock'], FILTER_VALIDATE_BOOLEAN);
}
file_put_contents('products.php', "<?php\n\nreturn " . var_export($rows, true) . ";\n");
echo file_get_contents('products.php'); var_export() writes long array() syntax with numeric indexes. Pass the delimiter as the third argument of fgetcsv() for semicolon files.
import csv, io
text = "sku,price,in_stock\nA-100,9.99,true\nB-200,15,false\n"
def php(value):
if isinstance(value, bool):
return "true" if value else "false"
if isinstance(value, (int, float)):
return str(value)
return "'" + str(value).replace("\\", "\\\\").replace("'", "\\'") + "'"
def cast(v):
if v.lower() in ("true", "false"):
return v.lower() == "true"
try:
return int(v) if v.isdigit() else float(v)
except ValueError:
return v
rows = csv.DictReader(io.StringIO(text))
lines = []
for row in rows:
pairs = ", ".join(php(k) + " => " + php(cast(v)) for k, v in row.items())
lines.append(" [" + pairs + "],")
print("<?php\n\nreturn [\n" + "\n".join(lines) + "\n];") Useful as a build step when the source of truth is a spreadsheet and the PHP project should not be parsing CSV at runtime.
PHP's CSV functions predate RFC 4180. They recognize a backslash escape character on top of the standard doubled quotes, so a field containing \" reads differently from what Excel would have written. Pass an empty string as the escape argument to get standard behavior; PHP 8.4's deprecation warning pushes code in that direction.
Converting also pays off at runtime because of OPcache. A file that returns a static array is compiled once and cached, so for a few thousand rows it loads faster than parsing the CSV on every request.
This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.
Yes. Each row becomes an associative array keyed by the header names, so the result is a list of rows ready for a foreach loop.
The short array syntax [] needs PHP 5.4 or newer, so every supported PHP version accepts it, PHP 8.x included.
Yes. Choose comma, semicolon, tab or pipe, or pick Custom and type your own delimiter. The output updates as soon as you change it.
Use fgetcsv() to read files at runtime. This tool is for static data you want to commit as code: seeders, lookup tables, test fixtures or config arrays.
Yes. Strings are single-quoted, and any single quote or backslash inside them is escaped, so the output is valid PHP.
PHP array to CSV converts in the other direction. For a language-neutral result use CSV to JSON, and the CSV table viewer shows what you are about to convert.