Home > database >  How to fetch data every second from MYSQL database
How to fetch data every second from MYSQL database

Time:09-16

I'm trying to make a Chat App using HTML, CSS, JS, PHP and Mysql.
I've completed all the functionalities that includes sending a message, receiving a message, displaying users... But the issue i'm facing is that i need to refresh the page every time i received a new message.

I'm looking for a way to auto update data with new data from mysql database.
Code:

<?php    
if ($_GET['id']){
        $id = $_GET['id'];
        $id = preg_replace("/[^0-9]/", "", $id);
        $fetching_messages = "SELECT * FROM users_messages WHERE from_user='$id' OR to_user='$id' ORDER BY id";
        $check_fetching_messages = $db->prepare($fetching_messages);
        $check_fetching_messages->execute();
        $messages_all = $check_fetching_messages->fetchAll();
    
      } else {
      }
?>

<div id="autodata">
        <?php foreach($to_users as $to_user) : ?>
          <?php
          $to_user_id = $to_user['to_user'];
          $to_user_name = "SELECT * FROM users_accounts WHERE id='$to_user_id'";
          $check_to_user_name = $db->query($to_user_name);

          while ($row_to_user_name = $check_to_user_name->fetch()) {
              $id_user = $row_to_user_name['id'];
              $username = $row_to_user_name['username'];
              $pdp = $row_to_user_name['profile_image'];

          }

          if ($id_user == $user_id){

          } else {
            echo '
            <form style="height: fit-content;" name="goto'.$to_user_id.'" action="inbox.php">
              <div onclick="window.location.replace('."'".'?id='.$to_user_id."'".')" class="inbox_chat_field_user">';
                if (empty($pdp)){
                  echo "<img class='inbox_chat_field_user_img' src='uploads\profile\default.jpg'/>";
                } else {
                echo "<img class='inbox_chat_field_user_img' src='".$pdp."'/>";
              }
              echo '
              <span class="inbox_chat_field_user_p">'.$username.'</span>
            </div>
          </form>
             <hr class="inbox_separing_hr">';
          }

          ?>

       <?php endforeach;?>
</div>

CodePudding user response:

Simply you can't do that, PHP is a server-side language, you can't tell the clients to refresh from PHP.

To accomplish that chat you should consider JavaScript in the browser.

The easiest way is by sending an AJAX request to your server and check if there are new messages every 5 or 10 seconds, and then do what you want with the messages in the response.

If you use jquery in your application you can send ajax request in this way:

$.get( "messages.php", function( data ) {
  console.log( "Data Loaded: "   data );
});

and in messages.php script, you can fetch new messages from the database and return them with HTML or JSON format

You may also use FCM service offered by firebase to push your messages to the client directly, Check this package for PHP FCM.

There are other solutions like websockets etc...

CodePudding user response:

It would have been easier for me to directly update your code had you separated business logic from presentation, so I am not going to attempt to do that. Instead I will describe a technique you can use and leave it to you to figure out the best way to use it. You might consider using server-sent events. See the JavaScript class EventSource.

The following "business logic" PHP program, sse_cgi.php, periodically has new output every 2 seconds (for a total of 5 times). In this case the output is just the current date and time as a string. But it could be, for example, a JSON record. Note the special header that it outputs:

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

$firstTime = True;
for ($i = 0; $i < 5; $i  ) {
    if (connection_aborted()) {
        break;
    }

    $curDate = date(DATE_ISO8601);
    echo 'data: This is a message at time ' . $curDate, "\n\n";

    // flush the output buffer and send echoed messages to the browser
    while (ob_get_level() > 0) {
        ob_end_flush();
    }
    flush();
    if ($i < 4) {
        sleep(2); # Sleep for 2 seconds
    }
}

And this is the presentation HTML that would be outputted. JavaScript code in this case is just replacing the old date with the updated value. It could just as well append new <li> elements to an existing <ul> tag or <tr> elements to an existing <table>.

<html>
<head>
   <meta charset="UTF-8">
   <title>Server-sent events demo</title>
</head>
<body>
  <div id='date'></div>

<script>
  var evtSource = new EventSource('sse_cgi.php');
  var date = document.getElementById('date');

  evtSource.onmessage = function(e) {
      // replace old content
      date.innerHTML = e.data;
  };

  evtSource.onerror = function() {
      // occurs when script terminates:
      evtSource.close();
      console.log('Done!');
  };

</script>
</body>
</html>

Note that this presentation references the "business logic" scripts that returns the successive dates.

Important Note

It is important to realize that this technique keeps the connection to the server open for the duration until all the data has been ultimately sent and the business logic script ultimately terminates (or the presentation running in the browser issues a call to evtSource.close() to close the connection). So if you have a lot of simultaneous users, this could be an issue.

If your application does not have a limited number of messages to return then the previously described problem can be overcome by having the business logic script return immediately after having sent one message. This will break the connection with the browser, which if it is still there, will automatically attempt to re-connect with the business logic script (note that this reconnection can take a while):

Updated Business Logic

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

# Simulate waiting for next message:
sleep(2);
$curDate = date(DATE_ISO8601);
echo 'data: This is a message at time ' . $curDate, "\n\n";

// flush the output buffer and send echoed messages to the browser
while (ob_get_level() > 0) {
    ob_end_flush();
}
flush();

Updated Presentation

<html>
<head>
   <meta charset="UTF-8">
   <title>Server-sent events demo</title>
</head>
<body>
  <div id='date'></div>

<script>
  var evtSource = new EventSource('sse_cgi.php');
  var date = document.getElementById('date');

  evtSource.onmessage = function(e) {
      // replace old content
      date.innerHTML = e.data;
  };

</script>
</body>
</html>
  • Related