簡単なSSEの実装
sseapi.php
php
1<?PHP
2header("Cache-Control: no-store");
3header("Content-Type: text/event-stream");
4date_default_timezone_set("Asia/Tokyo");
5while (true) {
6  $t=date("Y-m-d H:i:s");
7  print "data:{\"event\":\"message\",\"time\":\"$t\"}".PHP_EOL.PHP_EOL;
8  ob_end_flush(); 
9  flush();
10  if ( connection_aborted() ) break;
11  sleep(1);
12}
上記を利用してjsでこう呼び出す
html
1<script>
2const evtSource = new EventSource("sseapi.php",);
3evtSource.onmessage = function (event) {
4console.log(event.data );
5};
6</script>
chatの実装
だいぶ端折ってますが最低限動く範囲で実装しておきます
chat.html
html
1<script>
2window.addEventListener('DOMContentLoaded', ()=>{
3  const box=document.querySelector('#box');
4  const message=document.querySelector('#message');
5  const send=document.querySelector('#send');
6  send.addEventListener('click',e=>{
7    const usp=new URLSearchParams();
8    if(message.value){
9      usp.append('m',message.value);
10      fetch('sendapi.php?'+usp);
11      message.value='';
12    }
13  });
14  message.addEventListener('keydown',e=>{
15    if(e.key=="Enter"){
16      send.click();
17    }
18  });
19});
20const evtSource = new EventSource("sseapi.php",);
21evtSource.onmessage = function (event) {
22  const json=JSON.parse(event.data);
23  box.appendChild(Object.assign(document.createElement('div'),{textContent:json.message}));
24  box.scrollTop = box.scrollHeight;
25};
26</script>
27<style>
28#box{
29width:500px;
30height:300px;
31background-Color:lightgray;
32overflow-Y:scroll;
33}
34</style>
35<div id="box">
36</div>
37<input id="message"><input type="button" id="send" value="send">
sendapi.php
php
1<?PHP
2$m=filter_input(INPUT_GET,"m");
3if($m){
4  $filename="chat.txt";
5  $file = new SplFileObject($filename, "a+");
6  $file->fwrite('['.microtime(true).']'.$m.PHP_EOL);
7}
sseapi.php
php
1<?PHP
2header("Cache-Control: no-store");
3header("Content-Type: text/event-stream");
4date_default_timezone_set("Asia/Tokyo");
5$mt=microtime(true);
6while (true) {
7  $filename="chat.txt";
8  $file = new SplFileObject($filename, "r");
9  foreach ($file as $line) {
10    if(preg_match("/^\[([\d\.]+)\](.+?)$/",$line,$match)){
11      if($match[1]-$mt > 0){
12        print "data:{\"message\":".json_encode($match[2])."}".PHP_EOL.PHP_EOL;
13      }
14    }
15    ob_end_flush();
16    flush();
17  }
18  if ( connection_aborted() ) break;
19  $mt=microtime(true);
20  sleep(1);
21}