Skip to content

Instantly share code, notes, and snippets.

@shimarin
Last active August 16, 2024 12:49
Show Gist options
  • Save shimarin/cd45dafd2dba478b395cb1113dc01d2c to your computer and use it in GitHub Desktop.
Save shimarin/cd45dafd2dba478b395cb1113dc01d2c to your computer and use it in GitHub Desktop.
JavaScriptのEventSource APIにサーバー側でのファイル更新イベントを通知するためのエンドポイント
<?php
/**
* event.php
* JavaScriptのEventSource APIにサーバー側でのファイル更新イベントを通知するためのエンドポイント
*
* PHPにinotifyエクステンションが必要 https://github.com/arnaud-lb/php-inotify
*
* 2024 Tomoatsu Shimada
*/
// ポーリングのタイムアウトを設定
$timeout = 90; // Cloudflareがタイムアウトしないラインがこれくらい
// 変更(書き込みクローズ)をウォッチしたいファイルのリストを設定
$targets = ["index.html"];
// タイムアウト処理のため開始時刻を記録
$start_time = time();
// inotify インスタンスを作成
$inotify = inotify_init();
// 指定されたファイルを全てウォッチ開始
$watch_descriptors = array();
foreach ($targets as $target) {
$wd = inotify_add_watch($inotify, $target, IN_CLOSE_WRITE);
$watch_descriptors[$wd] = $target;
}
// EventSource向けのレスポンスヘッダを出力
header("Content-Type: text/event-stream");
header("Cache-Control: no-cache");
// 出力バッファを無効にする。以降の出力は全て即時に送信される
ob_implicit_flush(true);
ob_end_flush();
while (time() - $start_time < $timeout && connection_status() == CONNECTION_NORMAL) {
$read = [$inotify];
$write = null; $except = null;
$rst = stream_select($read,$write,$except, 1);
if ($rst === 0) continue; // no events
if ($rst === false) break; // stream_select failed
//else
$events = inotify_read($inotify);
if (!$events) break;
//else
foreach ($events as $event) {
$target = $watch_descriptors[$event["wd"]];
echo "data: {$target}\n\n";
flush();
}
}
// ウォッチャーを削除し、inotifyインスタンスを閉じる
foreach ($watch_descriptors as $watch_descriptor => $target) {
inotify_rm_watch($inotify, $watch_descriptor);
}
fclose($inotify);
/*
クライアント例:
<script>
// サーバーにファイルの更新を監視してもらい、更新されたらブラウザをリロードする
const eventSource = new EventSource('event.php');
eventSource.onmessage = function(event) {
if (event.data === 'index.html') {
window.location.reload(); // index.htmlの更新メッセージを受け取ったらリロード
}
};
</script>
*/
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment