Support more delimiters for CSV imports
MODIFY
app/Helper.php
app/Helper.php
@@ -13,4 +13,20 @@ class Helper
{
return (int) round($rawNumber * 100);
}
+
+ public static function detectDelimiter(string $line): string
+ {
+ $delimiters = [
+ ';' => 0,
+ ',' => 0,
+ '\t' => 0,
+ '|' => 0,
+ ];
+
+ foreach ($delimiters as $delimiter => &$count) {
+ $count = substr_count($line, $delimiter);
+ }
+
+ return array_search(max($delimiters), $delimiters);
+ }
}

MODIFY
app/Http/Controllers/ImportController.php
app/Http/Controllers/ImportController.php
@@ -58,8 +58,14 @@ class ImportController extends Controller
$headers = [];
$file = fopen(storage_path('app/imports/' . $import->file), 'r');
- $firstRow = fgetcsv($file, 999, ',');
+ // Detect delimiter
+ $firstRowRaw = fgets($file);
+ $delimiter = Helper::detectDelimiter($firstRowRaw);
+
+ rewind($file); // Reset file pointer to make sure fgetcsv() starts at first line
+
+ $firstRow = fgetcsv($file, 999, $delimiter);
foreach ($firstRow as $column) {
$headers[] = $column;
}
@@ -97,19 +103,18 @@ class ImportController extends Controller
$file = fopen(storage_path('app/imports/' . $import->file), 'r');
- $heading = true;
+ // Detect delimiter
+ $rawHeaderRow = fgets($file);
+ $delimiter = Helper::detectDelimiter($rawHeaderRow);
+
$rows = [];
- while ($row = fgetcsv($file, 999, ',')) {
- if (!$heading) {
+ while ($row = fgetcsv($file, 999, $delimiter)) {
$rows[] = [
'happened_on' => $row[$import->column_happened_on],
'description' => $row[$import->column_description],
'amount' => $row[$import->column_amount]
];
- } else {
- $heading = false;
- }
}
return view('imports.complete', compact('tags', 'rows'));

RENAME
tests/Unit/Models/HelperTest.php
tests/Unit/HelperTest.php
<?php
-namespace Tests\Unit\Models;
+namespace Tests\Unit;
use App\Helper;
use PHPUnit\Framework\TestCase;
@@ -34,4 +34,18 @@ class HelperTest extends TestCase
$this->assertEquals($case['expected'], $result);
}
}
+
+ public function testDelimiterDetection(): void
+ {
+ $testCases = [
+ 'hello|world' => '|',
+ 'id,name,address' => ',',
+ 'hello,goodbye|foo|bar' => '|',
+ 'id;description;amount;foo;bar' => ';'
+ ];
+
+ foreach ($testCases as $input => $expected) {
+ $this->assertEquals($expected, Helper::detectDelimiter($input));
+ }
+ }
}

Support more delimiters for CSV imports