ブラウザ上でCSVファイルを解析し、SPIRALのデータベースに一括登録するサンプルプログラムを紹介します。
注意点
・ 付属のJavaScript CSVパーサーは簡易的なものです。複雑なCSV(改行を含む値など)には対応できない場合があります。
・ 登録先のDB(サンプルでは`csvUpload`)と、CSVの列構成を事前に一致させておく必要があります。
・ CSVのヘッダー行にはフィールドの差し替えキーワードを入れる必要があります。
・ 登録先のDB(サンプルでは`csvUpload`)と、CSVの列構成を事前に一致させておく必要があります。
・ CSVのヘッダー行にはフィールドの差し替えキーワードを入れる必要があります。
実装の概要
このサンプルは、単一の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->doBulkInsert()を使用して、データをDBに一括登録する。
7. 処理結果のメッセージを画面に表示する。
サンプルコード
以下がサンプルコードです。この内容でページを作成してください。
<?//<!-- SMP_DYNAMIC_PAGE DISPLAY_ERRORS=ON NAME=XXX -->?> <?php // 処理結果メッセージ用 $message = null; if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['columns_json'], $_POST['data_json'])) { $columns = $_POST['columns_json']; $data = $_POST['data_json']; if (!is_array($columns) || !is_array($data)) { $message = 'データ形式が不正です'; } else { try { $db = $SPIRAL->getDataBase("csvUpload"); $chunks = array_chunk($data, 1000); foreach ($chunks as $chunk) { $db->doBulkInsert($columns, $chunk); } $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'; // DOM構築完了後に初期化 document.addEventListener('DOMContentLoaded', init, { once: true }); function init() { try { // 必須要素の存在チェック const input = document.getElementById('csvFile'); const columnsEl = document.getElementById('columnsJson'); const dataEl = document.getElementById('dataJson'); // どれか一つでも欠けていれば何もしない if (!input || !columnsEl || !dataEl) return; // ファイル選択時のみ動作 input.addEventListener('change', onFileChange); } catch (e) { // ここで例外を握りつぶすことで、他画面への影響を最小化 console.error('[csv script] init error:', e); } } async function onFileChange(ev) { const file = ev.target && ev.target.files ? ev.target.files[0] : null; if (!file) return; try { const text = await readFileAsText(file, 'UTF-8'); const parsed = parseCSV(text); if (!Array.isArray(parsed) || parsed.length < 2) { alert('データ行が不足しています(ヘッダー+1行以上が必要)'); return; } const columns = parsed[0]; const data = parsed .slice(1) // 空行・全要素空文字の行は除外 .filter(row => Array.isArray(row) && row.some(v => String(v ?? '') !== '')); // 必須IDを再取得(別DOMへの参照切れ対策) const columnsEl = document.getElementById('columnsJson'); const dataEl = document.getElementById('dataJson'); if (!columnsEl || !dataEl) return; // 念のため columnsEl.value = JSON.stringify(columns); dataEl.value = JSON.stringify(data); } catch (e) { console.error('[csv script] parse error:', e); alert('CSVの読み込みまたは解析でエラーが発生しました。ファイルの形式を確認してください。'); } } /** * File をテキストとして読む(BOM考慮) */ function readFileAsText(file, encoding = 'UTF-8') { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onerror = () => reject(reader.error); reader.onload = () => { let result = reader.result; // UTF-8 BOM除去 if (typeof result === 'string' && result.charCodeAt(0) === 0xFEFF) { result = result.slice(1); } resolve(result); }; reader.readAsText(file, encoding); }); } /** * シンプルCSVパーサ(ダブルクオート対応、CRLF対応) */ function parseCSV(text) { const rows = []; let row = []; let value = ''; let inQuotes = false; for (let i = 0; i < text.length; i++) { const char = text[i]; const next = text[i + 1]; if (inQuotes) { if (char === '"' && next === '"') { value += '"'; i++; } else if (char === '"') { inQuotes = false; } else { value += char; } } else { if (char === '"') { inQuotes = true; } else if (char === ',') { row.push(value); value = ''; } else if (char === '\n' || char === '\r') { // 改行(CRLF対応) if (char === '\r' && next === '\n') i++; row.push(value); value = ''; rows.push(row); row = []; } else { value += char; } } } // 最終セル・最終行を反映 if (value !== '' || row.length > 0) { row.push(value); rows.push(row); } return rows; } })(); </script> <?php endif; ?> </body> </html>
実行結果
ページにアクセスすると、ファイル選択ボタンが表示されます。
CSVファイルを選択して「アップロード」ボタンをクリックするとページがリロードされ、PHP処理の結果(成功またはエラーメッセージ)が表示されます。
まとめ
本記事では、JavaScriptでCSVを解析し、PHPでSPIRALのDBに登録する一連の流れを解説しました。
実際に活用される際はCSVファイルの中身に応じて適切なパースロジックを実装する必要があります。
実際に活用される際はCSVファイルの中身に応じて適切なパースロジックを実装する必要があります。