ブラウザ上でCSVファイルを解析し、SPIRALのデータベースに一括更新するサンプルプログラムを紹介します。
注意点
・ 付属のJavaScript CSVパーサーは簡易的なものです。複雑なCSV(改行を含む値など)には対応できない場合があります。
・ 更新先のDB(サンプルでは`csvUpload`)と、CSVの列構成を事前に一致させておく必要があります。
・ CSVのヘッダー行にはフィールドの差し替えキーワードを入れる必要があります。
・
・ 更新先のDB(サンプルでは`csvUpload`)と、CSVの列構成を事前に一致させておく必要があります。
・ CSVのヘッダー行にはフィールドの差し替えキーワードを入れる必要があります。
・
$keyNameには更新キーとなるフィールドの識別名及びヘッダーのカラム名と合致した物を入力してください。
実装の概要
このサンプルは、単一のPHPファイル内でクライアント処理とサーバー処理を完結させています。
1. ユーザーがファイル選択フォームでCSVファイルを選ぶ。
2. JavaScriptがファイルを読み込み、ヘッダー行とデータ行に分解してJSON文字列に変換する。
3. 変換したJSONを、フォーム内のhiddenフィールドにセットする。
4. ユーザーが「アップロード」ボタンを押すと、フォームが同じページにPOST送信される。
5. サーバーサイドのPHPがPOSTされたJSONデータを受け取る。
6.
7. 処理結果のメッセージを画面に表示する。
2. JavaScriptがファイルを読み込み、ヘッダー行とデータ行に分解してJSON文字列に変換する。
3. 変換したJSONを、フォーム内のhiddenフィールドにセットする。
4. ユーザーが「アップロード」ボタンを押すと、フォームが同じページにPOST送信される。
5. サーバーサイドのPHPがPOSTされたJSONデータを受け取る。
6.
$SPIRAL->doBulkUpdate()を使用して、データをDBに一括更新する。
7. 処理結果のメッセージを画面に表示する。
サンプルコード
以下がサンプルコードです。この内容でページを作成してください。
<?php //<!-- SMP_DYNAMIC_PAGE DISPLAY_ERRORS=ON NAME=XXX -->?> <?php $message = null; $keyName = "csvId"; //更新キーの識別名を入力してください。 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['columns_json'], $_POST['data_json'])) { $columns = $_POST['columns_json']; $data = $_POST['data_json']; if (is_string($columns)) $columns = json_decode($columns, true); if (is_string($data)) $data = json_decode($data, true); try { if (!is_array($columns) || !is_array($data)) { throw new Exception('columns_json / data_json が配列になっていません'); } $columns = array_values(array_map('strval', $columns)); $keyPos = array_search($keyName, $columns, true); if ($keyPos === false) throw new Exception("キー列 {$keyName} がヘッダーに存在しません"); // ヘッダー並べ替え(キー列を先頭) if ($keyPos !== 0) { [$columns[0], $columns[$keyPos]] = [$columns[$keyPos], $columns[0]]; } $colCount = count($columns); // 各行もキー列を先頭へ & 列数をそろえる & 数値添字化 foreach ($data as &$row) { if (!is_array($row)) $row = (array)$row; $row = array_values($row); // 足りない列は null で埋める/多い場合は切り詰め if (count($row) < $colCount) { $row = array_pad($row, $colCount, null); } elseif (count($row) > $colCount) { $row = array_slice($row, 0, $colCount); } // 並べ替え(元の keyPos と 0 をスワップ) if ($keyPos !== 0) { [$row[0], $row[$keyPos]] = [$row[$keyPos], $row[0]]; } foreach ($row as $i => $v) { if (is_array($v) || is_object($v)) $row[$i] = json_encode($v, JSON_UNESCAPED_UNICODE); } } unset($row); $db = $SPIRAL->getDataBase("csvUpload"); foreach (array_chunk($data, 1000) as $chunk) { $result = $db->doBulkUpdate($keyName, $columns, $chunk, "skip"); } $message = "一括更新完了"; } catch (Exception $e) { $message = "エラー:" . $e->getMessage(); } } ?> <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"><title>CSV一括更新</title> </head> <body> <?php if ($message): ?> <p><?php echo htmlspecialchars($message, ENT_QUOTES, 'UTF-8'); ?></p> <?php else: ?> <form id="csvForm" method="POST"> <input type="file" id="csvFile" accept=".csv" required> <input type="hidden" name="columns_json" id="columnsJson"> <input type="hidden" name="data_json" id="dataJson"> <button type="submit">CSVで一括更新</button> </form> <script> (function(){ 'use strict'; document.addEventListener('DOMContentLoaded', () => { const input = document.getElementById('csvFile'); const columnsEl = document.getElementById('columnsJson'); const dataEl = document.getElementById('dataJson'); if (!input || !columnsEl || !dataEl) return; input.addEventListener('change', async (ev) => { const file = ev.target.files && ev.target.files[0]; if (!file) return; const text = await file.text(); const parsed = parseCSV(stripBOM(text)); if (!Array.isArray(parsed) || parsed.length < 2) { alert('ヘッダー+1行以上が必要です'); return; } const columns = parsed[0]; const data = parsed.slice(1).filter(r => r.some(v => String(v ?? '') !== '')); columnsEl.value = JSON.stringify(columns); dataEl.value = JSON.stringify(data); }); }); function stripBOM(s){ return s.charCodeAt(0) === 0xFEFF ? s.slice(1) : s; } // ダブルクオート/CRLF対応の簡易CSVパーサ function parseCSV(text){ const rows = []; let row=[], val='', inQ=false; for (let i=0;i<text.length;i++){ const c=text[i], n=text[i+1]; if (inQ){ if (c === '"' && n === '"'){ val+='"'; i++; } else if (c === '"'){ inQ=false; } else { val+=c; } } else { if (c === '"'){ inQ=true; } else if (c === ','){ row.push(val); val=''; } else if (c === '\n' || c === '\r'){ if (c === '\r' && n === '\n') i++; row.push(val); val=''; rows.push(row); row=[]; } else { val+=c; } } } if (val !== '' || row.length) { row.push(val); rows.push(row); } return rows; } })(); </script> <?php endif; ?> </body> </html>
実行結果
ページにアクセスすると、ファイル選択ボタンが表示されます。
CSVファイルを選択して「アップロード」ボタンをクリックするとページがリロードされ、
PHP処理の結果(成功またはエラーメッセージ)が表示されます。
まとめ
本記事では、JavaScriptでCSVを解析し、PHPでSPIRALのDBに更新する一連の流れを解説しました。
実際に活用される際はCSVファイルの中身に応じて適切なパースロジックを実装する必要があります。
実際に活用される際はCSVファイルの中身に応じて適切なパースロジックを実装する必要があります。