Search code examples
javascriptphphtmlserver-sent-events

Server Side Events, HTML5, PHP & Javascript... index page not 'refreshing'


I found a really good article with a feature I want to add to a page, but have been stuck the entire day with one small error. For reference the tutorial is located here.

Everything is working, the only thing that is not happening is the fact that the index.php webpage is not refreshing on changes made to the hosted php array. Could anyone glance at my code and tell me if I have a typo or missed part of the article?

My array file - selectedSystemStateResults.php

<?php
$selectedSystemStateResults = ["cart", "dogsss", "cows", "zebra", "snake"];

My serverside PHP script file - selectedSystemState-script.php

<?php
header("Cache-Control: no-cache");
header("Content-Type: text/event-stream");

// Require the file which contains the $animals array
require_once "selectedSystemStateResults.php";

// Encode the php array in json format to include it in the response
$selectedSystemStateResults = json_encode($selectedSystemStateResults);

echo "data: $selectedSystemStateResults" . "\n\n";
flush();
echo "retry: 1000\n";
echo "event: selectedSystemStateResultsMessage\n";

My Client side web page - index.php

    <?php require "selectedSystemStateResults.php"; ?>
    <html>
      <body>
    <?php foreach ($selectedSystemStateResults as $selectedSystemStateResult) : ?>
            <li><?php echo $selectedSystemStateResult; ?></li>
          <?php endforeach ?>
        </ul>
    <script src="/selectedSystemState-script.js"></script> 
    </body>
    </html>

My javascript file - selectedSystemState-script.js

let eventSource = new EventSource('selectedSystemState-script.php');

eventSource.addEventListener("selectedSystemStateResultsMessage", function(event) {
  let data = JSON.parse(event.data);
  let listElements = document.getElementsByTagName("li");

  for (let i = 0; i < listElements.length; i++) {
    let selectedSystemStateResults = listElements[i].textContent;
    if (!data.includes(selectedSystemStateResults)) {
      listElements[i].style.color = "red";
    }
  }
});

I have read this and re-read this for the past 8 hours and feel really stuck. Does anyone see any blaring php or javascript typos or could the tutorial be wrong?

Please pardon the typo I had in the file names on my unedited original post. The directory shows the files all named properly.

Directory listing


Solution

  • Using this tutorial Using server-sent events

    I found out that the script.php file must NOT stop executing !!

    or (selectedSystemState-script.php) in your case .

    So I guess the the tutorial you linked is wrong in some point ?

    try this

    while (1) {
      // Every second, send a "selectedSystemStateResultsMessage" event.
    
      echo "event: selectedSystemStateResultsMessage\n";
      require("selectedSystemStateResults.php");
      $selectedSystemStateResults = json_encode($selectedSystemStateResults);
      echo "data: $selectedSystemStateResults" . "\n\n";
      ob_end_flush();
      flush();
      sleep(1);
    } 
    

    this is new to me but i noticed a few things :

    1- the php event script file must have header text/event-stream

    2- that file must not stop executing !

    3- event: is sent before data: .

    Hope this help

    EDIT After a test on your script It worked when I changed <script src="/selectedSystemState-script.js"></script>

    to <script src="./selectedSystemState-script.js"></script>

    it was calling selectedSystemState-script.js from root folder ! and generate 404 error

    and in selectedSystemState-script.php

    <?php
    header("Cache-Control: no-cache");
    header("Content-Type: text/event-stream");
    
    // Require the file which contains the $animals array
    require_once "selectedSystemStateResults.php";
    
    // Encode the php array in json format to include it in the response
    $selectedSystemStateResults = json_encode($selectedSystemStateResults);
    
    // data after event
    flush();
    echo "retry: 1000\n";
    echo "event: selectedSystemStateResultsMessage\n";
    echo "data: $selectedSystemStateResults" . "\n\n";
    ?>
    

    and I edited selectedSystemState-script.js a bit :

    let eventSource = new EventSource('selectedSystemState-script.php');
    
    eventSource.addEventListener("selectedSystemStateResultsMessage", function(event) {
      let data = JSON.parse(event.data);
      let listElements = document.getElementsByTagName("li");
    
      for (let i = 0; i < listElements.length; i++) {
        let selectedSystemStateResults = listElements[i].textContent;
        if (!data.includes(selectedSystemStateResults)) {
          listElements[i].style.color = "red";
        } else {
            listElements[i].style.color = "blue";
        }
      }
    });