ブラウザ上で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ファイルの中身に応じて適切なパースロジックを実装する必要があります。