PHPとcURLを用いたChatWork APIからのメッセージ取得と表示

通信・サーバー
この記事は約26分で読めます。

この記事では、PHPとcURLを使用してChatWork APIと連携し、特定のルームやユーザーからメッセージを取得し、JSONファイルに保存し、ウェブページに表示する方法を解説します。また、APIデータの取り扱いやログの出力、デバッグのベストプラクティスについても触れていきます。

はじめに

現代のウェブ開発では、APIとの連携が不可欠です。この記事では、PHPのcURLライブラリを使ってChatWork APIと連携し、特定のルームやユーザーからメッセージを取得する方法を紹介します。取得したデータをJSONファイルに保存し、ウェブページ上で表示するまでの一連の流れを解説します。

前提条件

  • 基本的なPHPとウェブ開発の知識
  • PHPがインストールされたウェブサーバーへのアクセス
  • ChatWorkアカウントとAPIトークン
  • cURL拡張モジュールが有効になっていること

作成するファイル

main.php
message_display.php
style.css
messages.json↠自動で作成

main.php

  • このプロジェクトの中心となるコードです。
  • ChatWork APIからメッセージを取得し、フィルタリング・保存・表示を管理します。
  • 必要に応じてmessage_display.phpを呼び出し、messages.jsonを自動生成します。

message_display.php

  • メッセージをHTML形式で表示するためのコードです。
  • main.phpから渡されたデータを受け取り、見た目を整えた状態で出力します。

style.css

  • 表示のデザインやスタイルを定義するCSSファイルです。
  • メッセージリストや全体のレイアウトを整え、視覚的に分かりやすくする役割を担います。

messages.json

ChatWork APIから取得したメッセージを保存し、次回以降のデータ読み込みを効率化します。

main.phpの処理によって自動生成されるJSONファイルです。

APIアクセスの設定

まず、ChatWork APIにアクセスするための設定を行います。APIトークンはChatWorkのアカウント設定から取得できます。

<?php
$api_key = 'keykeykeykeykeykeykeykeykeykeykey';
$room_id = '000000000'; // 取得したいルームのID
$target_user_name = '孫悟空'; // フィルタリングするユーザー名
$file_path = 'messages.json'; // メッセージを保存するJSONファイルのパス
PHP

$api_key: あなたのChatWork APIトークン
$room_id: メッセージを取得するルームのID
$target_user_name: フィルタリング対象のユーザー名
$file_path: メッセージを保存するJSONファイルのパス

ChatWork APIからのメッセージ取得

次に、ChatWork APIからメッセージを取得する関数を作成します。

function getMessagesFromUser($api_key, $room_id, $target_user_name) {
    $url = "https://api.chatwork.com/v2/rooms/$room_id/messages?force=1";

    // リクエスト情報をコンソールに出力
    echo '<script>';
    echo 'console.log("Messages API読み込み中: ' . $url . '");';
    echo '</script>';

    // cURLの初期化と設定
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-ChatWorkToken: ' . $api_key]);

    // APIリクエストの実行
    $result = curl_exec($ch);
    curl_close($ch);

    // エラーチェック
    if (!$result) {
        return ['error' => 'Failed to fetch messages'];
    }

    // JSONデコード
    $messages = json_decode($result, true);

    // 特定ユーザーのメッセージをフィルタリング
    return array_filter($messages, function ($message) use ($target_user_name) {
        return isset($message['account']['name']) && $message['account']['name'] === $target_user_name;
    });
}
PHP

解説

  • cURLの初期化と設定: curl_init()でcURLセッションを初期化し、必要なオプションを設定します。
  • HTTPヘッダーの設定: curl_setopt()でAPIキーを含むHTTPヘッダーを設定します。
  • APIリクエストの実行: curl_exec()でAPIリクエストを実行し、結果を取得します。
  • エラーチェック: リクエストが失敗した場合、エラーメッセージを返します。
  • JSONデコード: 取得したJSONデータを連想配列にデコードします。
  • メッセージのフィルタリング: array_filter()を使って、特定のユーザーからのメッセージのみを抽出します。

メッセージのローカル保存

取得したメッセージをローカルのJSONファイルに保存します。

if (file_exists($file_path)) {
    // ファイルの最終更新日時を取得
    $last_modified_time = filemtime($file_path);

    // 人間が読みやすい形式に変換
    $formatted_time = date('Y-m-d H:i:s', $last_modified_time);
    echo '<script>';
    echo 'console.log("jsonファイル更新:' . $formatted_time . '");';
    echo '</script>';
} else {
    echo "File does not exist.";
}

// JSONファイルが存在するか確認
if (file_exists($file_path)) {
    // ファイルが存在する場合、その内容を読み込む
    $json_data = file_get_contents($file_path);
    $messages = json_decode($json_data, true);
    echo '<script>';
    echo 'console.log("ローカルで読み込み:' . $file_path . '");';
    echo '</script>';
} else {
    // ファイルが存在しない場合、APIからデータを取得して保存
    $messages = getMessagesFromUser($api_key, $room_id, $target_user_name);
    $json_data = json_encode($messages, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    file_put_contents($file_path, $json_data);
    echo "Messages API読み込み中.\n";
}
PHP

解説

  • ファイルの存在確認: file_exists()でJSONファイルの存在を確認します。
  • ファイルの最終更新日時の取得: filemtime()でファイルの最終更新日時を取得し、コンソールに出力します。
  • ファイルの読み込み: ファイルが存在する場合、file_get_contents()で内容を読み込みます。
  • APIからのデータ取得と保存: ファイルが存在しない場合、APIからデータを取得し、file_put_contents()でファイルに保存します。

メッセージの表示

取得したメッセージをウェブページ上に表示します。ここでは、message_display.phpというファイルをインクルードしています。

include 'message_display.php';
PHP

main.phpで取得・保存されたメッセージデータを受け取り、HTML形式で表示。

<h1>Chatwork Messages</h1>

<h2>リクエスト情報</h2>
<ul>
    <li><strong>API Key:</strong> <?php echo htmlspecialchars($api_key); ?></li>
    <li><strong>Room ID:</strong> <?php echo htmlspecialchars($room_id); ?></li>
    <li><strong>Target User:</strong> <?php echo htmlspecialchars($target_user_name); ?></li>
</ul>

<h2>レスポンス情報</h2>
<?php if (!empty($messages)): ?>
    <?php foreach ($messages as $message): ?>
        <div class="message-container">
            <img src="<?php echo htmlspecialchars($message['account']['avatar_image_url']); ?>" alt="Avatar" class="avatar">
            <p><strong>アカウントID:</strong> <?php echo htmlspecialchars($message['account']['account_id']); ?></p>
            <p><strong>ユーザー:</strong> <?php echo htmlspecialchars($message['account']['name']); ?></p>
            <p><strong>メッセージID:</strong> <?php echo htmlspecialchars($message['message_id']); ?></p>
            <p><strong>送信日時:</strong> <?php echo date('Y-m-d H:i:s', $message['send_time']); ?></p>
            <p><strong>本文</p>
            <p class="m_body"><?php echo nl2br(htmlspecialchars($message['body'])); ?></p>
        </div>
    <?php endforeach; ?>
<?php else: ?>
    <p>No messages found for the user '<?php echo htmlspecialchars($target_user_name); ?>'.</p>
<?php endif; ?>
message_display.php

メッセージリストや画面全体のデザインを定義。見た目を整え、ユーザーフレンドリーなUIを構築しました。

/* 全体のスタイル */
body {
  font-family: Arial, sans-serif;
  background-color: #f4f6f9;
  width: 80%;
  margin: 0 auto;
  padding: 0;
  color: #333;
  min-height: 100vh;
}
/* 画面幅が640px以下の場合のスタイル */
@media (max-width: 840px) {
  body {
      width: 100%; /* 幅を100%に変更 */
      min-width: auto; 
      margin: 5px auto; /* 上下の余白を5pxに設定 */
  }
}
p {
  width: 100%;
  overflow-wrap: break-word; /* 長い単語を折り返す */
  word-break: break-word;   /* 行を切る(より積極的) */
}
/* コンテナ */
.container {
  width: 90%;
  max-width: 800px;
  background-color: #ffffff;
  border-radius: 10px;
  padding: 20px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

/* 見出し */
h1 {
  text-align: center;
  color: #007bff;
}

h2 {
  color: #007bff;
  border-bottom: 2px solid #eaf4fe;
  padding-bottom: 5px;
  margin-bottom: 15px;
}

/* リクエスト情報リスト */
.request-info {
  list-style: none;
  padding: 0;
}

.request-info li {
  margin-bottom: 10px;
  color: #555;
}

/* メッセージリスト */
.message-list {
  margin-top: 20px;
}

/* 各メッセージコンテナ */
.message-container {
  /* display: flex; */
  align-items: flex-start;
  margin-bottom: 20px;
  padding: 15px;
  background-color: #eaf4fe;
  border-radius: 10px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.m_body {
  background-color: #ffffff;
  font-weight: normal;
}
.message-container:last-child {
  margin-bottom: 0;
}

/* アバター画像 */
.avatar {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  margin-right: 15px;
}

/* メッセージ内容 */
.message-content {
  flex: 1;
}

.message-content p {
  margin: 0;
  color: #333;
  word-break: break-word;
}

/* 時刻のスタイル */
.message-content .time {
  display: block;
  margin-top: 10px;
  font-size: 0.8em;
  color: #999;
  text-align: right;
}
CSS

ログとデバッグ

デバッグやログのために、コンソールに情報を出力する関数を作成します。

function console_log($data, $label = '') {
    echo '<script>';
    if ($label) {
        echo 'console.log("' . $label . ': ", ' . json_encode($data) . ');';
    } else {
        echo 'console.log(' . json_encode($data) . ');';
    }
    echo '</script>';
}

// リクエスト情報をコンソールに出力
console_log($room_id, 'Room ID');
console_log($target_user_name, 'Target User');

if (isset($messages)) {
    // レスポンス情報をコンソールに出力
    console_log($messages, 'Messages');
}
?>
PHP

解説

  • console_log関数: PHPからJavaScriptのconsole.logを利用してデータを出力します。
  • デバッグ情報の出力: 変数の値や取得したメッセージをコンソールに出力することで、デバッグを容易にします。

ログとデバッグはhtmlで必要な情報を表示させるので、なくても大丈夫です。

まとめ

この記事では、PHPとcURLを用いてChatWork APIから特定のメッセージを取得し、JSONファイルに保存し、ウェブページに表示する方法を解説しました。また、デバッグやログのためのテクニックも紹介しました。APIとの連携はウェブ開発において重要なスキルであり、これらの手法を活用することで、より高度なアプリケーションを開発できるようになります。

後コードをまとめたので、こちらもお使いください。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="style.css?v=1.0">
</head>
<body>
<?php
$api_key = 'keykeykeykeykeykeykeykeykeykeykey';
$room_id = '000000000'; // 取得したいルームのID
$target_user_name = '孫悟空'; // フィルタリングするユーザー名
$file_path = 'messages.json'; // メッセージを保存するJSONファイルのパス

function getMessagesFromUser($api_key, $room_id, $target_user_name) {
    $url = "https://api.chatwork.com/v2/rooms/$room_id/messages?force=1";

    // リクエスト情報をコンソールに出力
    echo '<script>';
    echo 'console.log("Messages API読み込み中: ' . $url . '");';
    echo '</script>';

    // cURLの初期化と設定
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ['X-ChatWorkToken: ' . $api_key]);

    // APIリクエストの実行
    $result = curl_exec($ch);
    curl_close($ch);

    // エラーチェック
    if (!$result) {
        return ['error' => 'Failed to fetch messages'];
    }

    // JSONデコード
    $messages = json_decode($result, true);

    // 特定ユーザーのメッセージをフィルタリング
    return array_filter($messages, function ($message) use ($target_user_name) {
        return isset($message['account']['name']) && $message['account']['name'] === $target_user_name;
    });
}
if (file_exists($file_path)) {
    // ファイルの最終更新日時を取得
    $last_modified_time = filemtime($file_path);

    // 人間が読みやすい形式に変換
    $formatted_time = date('Y-m-d H:i:s', $last_modified_time);
    echo '<script>';
    echo 'console.log("jsonファイル更新:' . $formatted_time . '");';
    echo '</script>';
} else {
    echo "File does not exist.";
}

// JSONファイルが存在するか確認
if (file_exists($file_path)) {
    // ファイルが存在する場合、その内容を読み込む
    $json_data = file_get_contents($file_path);
    $messages = json_decode($json_data, true);
    echo '<script>';
    echo 'console.log("ローカルで読み込み:' . $file_path . '");';
    echo '</script>';
} else {
    // ファイルが存在しない場合、APIからデータを取得して保存
    $messages = getMessagesFromUser($api_key, $room_id, $target_user_name);
    $json_data = json_encode($messages, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    file_put_contents($file_path, $json_data);
    echo "Messages API読み込み中.\n";
}
include 'message_display.php';
function console_log($data, $label = '') {
    echo '<script>';
    if ($label) {
        echo 'console.log("' . $label . ': ", ' . json_encode($data) . ');';
    } else {
        echo 'console.log(' . json_encode($data) . ');';
    }
    echo '</script>';
}

// リクエスト情報をコンソールに出力
console_log($room_id, 'Room ID');
console_log($target_user_name, 'Target User');

if (isset($messages)) {
    // レスポンス情報をコンソールに出力
    console_log($messages, 'Messages');
}
?>
</body>
</html>
main.php
<h1>Chatwork Messages</h1>

<h2>リクエスト情報</h2>
<ul>
    <li><strong>API Key:</strong> <?php echo htmlspecialchars($api_key); ?></li>
    <li><strong>Room ID:</strong> <?php echo htmlspecialchars($room_id); ?></li>
    <li><strong>Target User:</strong> <?php echo htmlspecialchars($target_user_name); ?></li>
</ul>

<h2>レスポンス情報</h2>
<?php if (!empty($messages)): ?>
    <?php foreach ($messages as $message): ?>
        <div class="message-container">
            <img src="<?php echo htmlspecialchars($message['account']['avatar_image_url']); ?>" alt="Avatar" class="avatar">
            <p><strong>アカウントID:</strong> <?php echo htmlspecialchars($message['account']['account_id']); ?></p>
            <p><strong>ユーザー:</strong> <?php echo htmlspecialchars($message['account']['name']); ?></p>
            <p><strong>メッセージID:</strong> <?php echo htmlspecialchars($message['message_id']); ?></p>
            <p><strong>送信日時:</strong> <?php echo date('Y-m-d H:i:s', $message['send_time']); ?></p>
            <p><strong>本文</p>
            <p class="m_body"><?php echo nl2br(htmlspecialchars($message['body'])); ?></p>
        </div>
    <?php endforeach; ?>
<?php else: ?>
    <p>No messages found for the user '<?php echo htmlspecialchars($target_user_name); ?>'.</p>
<?php endif; ?>
message_display
/* 全体のスタイル */
body {
  font-family: Arial, sans-serif;
  background-color: #f4f6f9;
  width: 80%;
  margin: 0 auto;
  padding: 0;
  color: #333;
  min-height: 100vh;
}
/* 画面幅が640px以下の場合のスタイル */
@media (max-width: 840px) {
  body {
      width: 100%; /* 幅を100%に変更 */
      min-width: auto; 
      margin: 5px auto; /* 上下の余白を5pxに設定 */
  }
}
p {
  width: 100%;
  overflow-wrap: break-word; /* 長い単語を折り返す */
  word-break: break-word;   /* 行を切る(より積極的) */
}
/* コンテナ */
.container {
  width: 90%;
  max-width: 800px;
  background-color: #ffffff;
  border-radius: 10px;
  padding: 20px;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}

/* 見出し */
h1 {
  text-align: center;
  color: #007bff;
}

h2 {
  color: #007bff;
  border-bottom: 2px solid #eaf4fe;
  padding-bottom: 5px;
  margin-bottom: 15px;
}

/* リクエスト情報リスト */
.request-info {
  list-style: none;
  padding: 0;
}

.request-info li {
  margin-bottom: 10px;
  color: #555;
}

/* メッセージリスト */
.message-list {
  margin-top: 20px;
}

/* 各メッセージコンテナ */
.message-container {
  /* display: flex; */
  align-items: flex-start;
  margin-bottom: 20px;
  padding: 15px;
  background-color: #eaf4fe;
  border-radius: 10px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.m_body {
  background-color: #ffffff;
  font-weight: normal;
}
.message-container:last-child {
  margin-bottom: 0;
}

/* アバター画像 */
.avatar {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  margin-right: 15px;
}

/* メッセージ内容 */
.message-content {
  flex: 1;
}

.message-content p {
  margin: 0;
  color: #333;
  word-break: break-word;
}

/* 時刻のスタイル */
.message-content .time {
  display: block;
  margin-top: 10px;
  font-size: 0.8em;
  color: #999;
  text-align: right;
}
style.css

コメント