簡単な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}