ブラウザ上でCSVファイルを解析し、SPIRALのデータベースに一括登録するサンプルプログラムを紹介します。
注意点
・ このサンプルは、SPIRALのページで動作することを前提としています。
・ 登録先のDBと、CSVの列構成を事前に一致させておく必要があります。
・ CSVのヘッダー行にはDBの識別名を入れる必要があります。
・ 登録先のDBと、CSVの列構成を事前に一致させておく必要があります。
・ CSVのヘッダー行にはDBの識別名を入れる必要があります。
実装の概要
1. ユーザーがファイル選択フォームでCSVファイルを選ぶ。
2. JavaScriptがファイルを読み込み、ヘッダー行とデータ行に分解してJSON文字列に変換する。
3. 変換したJSONを、フォーム内のhiddenフィールドにセットする。
4. ユーザーが「アップロード」ボタンを押すと、フォームが同じページにPOST送信される。
5. サーバーサイドのPHPがPOSTされたJSONデータを受け取る。
6.
を使用して、データをDBに一括登録する。
7. 処理結果のメッセージを画面に表示する。
2. JavaScriptがファイルを読み込み、ヘッダー行とデータ行に分解してJSON文字列に変換する。
3. 変換したJSONを、フォーム内のhiddenフィールドにセットする。
4. ユーザーが「アップロード」ボタンを押すと、フォームが同じページにPOST送信される。
5. サーバーサイドのPHPがPOSTされたJSONデータを受け取る。
6.
$commonBase->apiCurlAction("POST", "/apps/" . APP_ID . "/dbs/" . DB_ID . "/records/bulk", $payload);
を使用して、データをDBに一括登録する。
7. 処理結果のメッセージを画面に表示する。
HTMLコード (bodyタブ)
まず、ユーザーが操作する画面を作成します。
<!-- 登録結果メッセージの表示 --> <p th:if="${cp.result.value['result'] != null}" th:text="${cp.result.value['result']}"></p> <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>
JavaScriptコード (JavaScriptタブ)
次に、クライアントサイドの動作を担当するJavaScriptです。
CSVファイルを解析し、フォーム送信用のデータを作成します。
document.addEventListener('DOMContentLoaded', function () { function parseCSV(text) { const rows = []; let row = []; let value = ''; let inQuotes = false; let i = 0; while (i < text.length) { 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') { if (char === '\r' && next === '\n') i++; row.push(value); value = ''; rows.push(row); row = []; } else { value += char; } } i++; } if (value !== '' || row.length > 0) { row.push(value); rows.push(row); } return rows; } document.getElementById('csvFile').addEventListener('change', function () { const file = this.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function (e) { const csvText = e.target.result; const parsed = parseCSV(csvText); if (parsed.length < 2) { alert('データ行が不足しています'); return; } const columns = parsed[0]; const data = parsed.slice(1).filter(row => row.length > 0 && row.some(v => v !== '')); document.getElementById('columnsJson').value = JSON.stringify(columns); document.getElementById('dataJson').value = JSON.stringify(data); }; reader.readAsText(file, 'UTF-8'); }); });
PHPコード (PHPタブ)
最後に、サーバーサイドでAPI連携を行うPHPスクリプトです。
フォームからPOSTされたJSONデータを受け取り、SPIRAL APIを呼び出してDB登録処理を実行します。
<?php //------------------------------ // 設定値 //------------------------------ define("API_URL", "https://api.spiral-platform.com/v1"); define("API_KEY", ""); define("APP_ROLE", ""); define("APP_ID", ""); define("DB_ID", ""); $columns = $SPIRAL->getParams("columns_json"); $data = $SPIRAL->getParams("data_json"); // POST受信処理 if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($columns, $data) && $columns && $data) { if (isset($columns[0]) && is_string($columns[0]) && str_starts_with($columns[0], '[')) { $columns = json_decode($columns[0], true); } if (isset($data[0]) && is_string($data[0]) && str_starts_with($data[0], '[')) { $data = json_decode($data[0], true); } if (!is_array($columns) || !is_array($data)) { $message = "データ形式が不正です"; } else { $commonBase = CommonBase::getInstance(); $records = []; foreach ($data as $row) { $record = []; foreach ($columns as $index => $col) { if (isset($row[$index])) { $record[$col] = $row[$index]; } } $records[] = $record; } $payload = ["records" => $records]; $result = $commonBase->apiCurlAction("POST", "/apps/" . APP_ID . "/dbs/" . DB_ID . "/records/bulk", $payload); if (isset($result["ids"]) && is_array($result["ids"])) { $message = "アップロードと登録に成功しました(ID: " . implode(", ", $result["ids"]) . ")"; } else { $message = "登録エラー:" . json_encode($result, JSON_UNESCAPED_UNICODE); } } $SPIRAL->setTHValue("result", $message); } else { $SPIRAL->setTHValue("result", ""); } //------------------------------ // 共通モジュール //------------------------------ class CommonBase { /** * シングルトンインスタンス * @var UserManager */ protected static $singleton; public function __construct() { if (self::$singleton) { throw new Exception('must be singleton'); } self::$singleton = $this; } /** * シングルトンインスタンスを返す * @return UserManager */ public static function getInstance() { if (!self::$singleton) { return new CommonBase(); } else { return self::$singleton; } } /** * V2用 API送信ロジック * @return Result */ function apiCurlAction($method, $addUrlPass, $data = null, $multiPart = null, $jsonDecode = null) { $header = array( "Authorization:Bearer ". API_KEY, "X-Spiral-Api-Version: 1.1", ); if($multiPart) { $header = array_merge($header, array($multiPart)); } else { $header = array_merge($header, array("Content-Type:application/json")); } if(APP_ROLE){ $header = array_merge($header, array("X-Spiral-App-Role: ".APP_ROLE)); } // curl $curl = curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_URL, API_URL. $addUrlPass); curl_setopt($curl, CURLOPT_HTTPHEADER, $header); if ($method == "POST") { if ($multiPart) { curl_setopt($curl, CURLOPT_POSTFIELDS, $data); } else { curl_setopt($curl, CURLOPT_POSTFIELDS , json_encode($data)); } curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); } if ($method == "PATCH") { curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); } if ($method == "DELETE") { curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); } $response = curl_exec($curl); if (curl_errno($curl)) echo curl_error($curl); curl_close($curl); if($jsonDecode){ return $response; }else{ return json_decode($response, true); } } } ?>
実行結果
ページにアクセスすると、ファイル選択フォームが表示されます。
CSVファイルを選択して「アップロード」ボタンをクリックすると、
ページがリロードされ、処理結果(成功またはエラーメッセージ)が画面上部に表示されます。
まとめ
本記事では、JavaScriptでCSVを解析し、PHPでSPIRALのDBに登録する一連の流れを解説しました。
実際に活用される際はCSVファイルの中身に応じて適切なパースロジックを実装する必要があります。
実際に活用される際はCSVファイルの中身に応じて適切なパースロジックを実装する必要があります。