ブラウザ上でCSVファイルを解析し、SPIRALのデータベースに一括登録するサンプルプログラムを紹介します。
注意点
・ このサンプルは、SPIRALのページで動作することを前提としています。
・ 登録先のDBと、CSVの列構成を事前に一致させておく必要があります。
・ CSVのヘッダー行にはフィールドの識別名を入れる必要があります。
・ 登録先のDBと、CSVの列構成を事前に一致させておく必要があります。
・ CSVのヘッダー行にはフィールドの識別名を入れる必要があります。
実装の概要
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ファイルの中身に応じて適切なパースロジックを実装する必要があります。