開発情報・ナレッジ

投稿者: ShiningStar株式会社 2025年10月31日 (金)

別ページに設置したPHPにて非同期通信でデータ検証をするサンプル

本記事では、別ページに設置したPHPを活用して、非同期通信を用いたシンプルなデータ検証システムを実装する方法をご紹介します。
この仕組みでは、ユーザが入力したテキストを別ページのPHPで検証し、その結果をフロントエンドで即時にフィードバックすることが可能です。
今回のサンプルでは、固定値との一致確認を例にしていますが、実際にはデータベース照合や外部APIとの連携など、より複雑な検証ロジックを組み込むこともできます。

以下、各パートごとにコード例とその解説を掲載していますので、ぜひご参考ください。

全体像

このサンプルは、以下の2つの主要なパートで構成されています:

検証用PHP ユーザから送信された入力値を検証し、結果をJSON形式で返却します。
入力値をinputTextとして送信し、valueが「hoge」であるかを判定するシンプルな検証をしています。
フロントエンド(HTML/JavaScript/CSS)(PHP) ユーザの入力値を取得し、非同期通信を通じて検証用PHPに送信します。
検証結果に応じ、入力エラーの場合は登録ボタンを無効化するなど、ユーザに分かりやすいフィードバックを提供します。

注意点

入力フィールドのname属性やクラス名は、実際の環境に合わせて適宜変更してください。
ページのURLも、実際の環境に合わせて正しく設定してください。
エラーハンドリングや通信エラー時の処理を充実させることで、ユーザにとって分かりやすいフィードバックを提供できます。

DB連携の可能性

本サンプルでは固定値との照合を行っていますが、実際の運用ではデータベースに保存された値との突合や、複数条件での検証も可能です。
ユーザ情報や検証結果の履歴をデータベースに保存することで、後日の分析や不正アクセスの監視など、より高度なシステム運用が実現します。

検証用ページのコード例

ページのPHPタブに、以下のPHPコードを記述することで、入力値の検証用APIを構築できます。
必要に応じて、認証処理やDB連携などの機能を追加して、セキュアかつ柔軟なシステムに仕上げてください。

【PHP】
<?php
// 入力値は「inputText」というキーで送信される前提です
$inputText = $SPIRAL->getParam("inputText");

if (!isset($inputText)) {
    $response = [
        'status' => 'failed',
        'errorMessage' => 'inputTextパラメータが存在しないか形式が不正です'
        ];
    $SPIRAL->setTHValue("response",$response);
    return;
}

// 検証対象の値(例として "hoge" を使用)
$checkValue = "hoge";

// ここでは、入力値と定義値の一致を検証します。
// 実際には、データベース照合や外部APIとの連携も可能です。
if ($inputText === $checkValue) {
    $response = [
        'status' => 'success'
        ];
    $SPIRAL->setTHValue("response",$response);
} else {
    $response = [
        'status' => 'failed',
        'errorMessage' => '照合エラー'
        ];
    $SPIRAL->setTHValue("response",$response);
}
?>
            
【編集箇所】
// 検証対象の値(例として "hoge" を使用)
$checkValue = "hoge";
                
【HTML】
<p th:text="${cp.result.value['response']}"></p>
            
ページ上のBODYはこのタグのみの記載としてください。

検証用フロントエンドコード例

ユーザ入力の検証は、JavaScriptの非同期通信機能を利用して行います。
下記のコードは、ユーザの入力値を取得し、別ページのPHPに送信して検証結果をUIに反映する仕組みを示しています。

【フロント:Javascript】
document.addEventListener("DOMContentLoaded", function () {
  const checkFieldName = "inputText"; // チェック対象のinput要素のname属性
  const API_URL = 'https://spiral-site.com/testBackend'; // PHPを設置したページのURLに変更してください

  // 入力フィールド、送信ボタン、結果表示領域の取得
  const inputField = document.querySelector("[name='" + checkFieldName + "']");
  const submitButton = document.querySelector(".sp-form-next-button");
  const resultMessage = document.getElementById("result");

  if (!inputField) {
    console.error("要素 [name='" + checkFieldName + "'] が見つかりません");
    return;
  }

  /*
   * PHPを呼び出して検証を実施する処理
  */
   async function performValidation(value) {
     try {
       const response = await fetch(API_URL, {
         method: "POST",
         headers: {
           "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
           "Accept": "text/html"
         },
         body: new URLSearchParams({ inputText: value }).toString(),
         credentials: "include"
       });

       const text = await response.text();
       console.log("status:", response.status, "body:", text);

       // HTMLから<p>タグの中身を抽出
       const match = text.match(/<p[^>]*>\s*(\{[^}]+\})\s*<\/p>/i);
       if (!match) {
         return { status: "error", errorMessage: "HTML内に結果<p>が見つかりません" };
       }

       const content = match[1]; // {status=success, errorMessage=hoge}

       // 中身をパース(=区切りを:に変換してJSON風に整形)
       const obj = {};
       content
         .replace(/[{}]/g, "")
         .split(",")
         .forEach(pair => {
           const [key, val] = pair.split("=").map(s => s.trim());
           if (key) obj[key] = val || "";
         });

       // 想定フォーマットに変換して返す
       return {
         status: obj.status || "error",
         data: { status: obj.status || "" },
         errorMessage: obj.errorMessage || ""
       };

     } catch (error) {
       throw new Error("通信エラー");
     }
   }

  /**
   * UIの更新を担当する処理
   * @param {Object} options
   * @param {string} options.message - 表示するメッセージ
   * @param {string} options.color - メッセージの色
   * @param {boolean} options.isValid - 登録ボタンの有効状態(true:有効、false:無効)
   */
  function updateUI({ message, color, isValid }) {
    resultMessage.textContent = message;
    resultMessage.style.color = color;
    if (submitButton) {
      submitButton.disabled = !isValid;
    }
  }

  /**
   * 全体の検証処理(入力チェック → ページ呼び出し → UI更新)を実施する関数
   */
  window.validate = async function () {
    const checkValue = inputField.value;

    if (!checkValue) {
      updateUI({ message: "値を入力してください", color: "red", isValid: false });
      return;
    }

    try {
      const data = await performValidation(checkValue);
      if (data.status === "success" && data.data && data.data.status === "success") {
        updateUI({ message: "success", color: "green", isValid: true });
      } else {
        const errorMsg = (data.data && data.data.errorMessage) || data.errorMessage || "不明なエラー";
        updateUI({ message: "エラー: " + errorMsg, color: "red", isValid: false });
      }
    } catch (error) {
      updateUI({ message: error.message, color: "red", isValid: false });
    }
  };
});
                
【編集箇所】
const checkFieldName = "inputText"; // チェック対象のinput要素のname属性
const API_URL = 'https://spiral-site.com/testBackend'; // PHPを設置したページのURLに変更してください
                
【フロント:HTML】
<input type="text" name="inputText">
<p id="result"></p>
<button type="button" onclick="validate()">検証</button>
                
【フロント:CSS】
/* 必要に応じてスタイルを追加してください */
#result {
    font-size: 1.2em;
    margin-top: 10px;
}
.sp-form-next-button:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}
                

最後に

上記のコード例を元に、シンプルな入力値検証システムを実装できます。
実運用では、セキュリティ対策やエラーハンドリング、データベース連携などの機能を追加することで、より堅牢なシステムへと発展させることが可能です。
本記事が、非同期通信の理解に役立つことを願っています。

不具合やご質問がある場合は、下記の「コンテンツに関しての要望はこちら」からご連絡ください。
解決しない場合はこちら コンテンツに関しての
要望はこちら