as far as I know you can't use socket.io with PHP. Here is the solution to your problem: Use websockets through a library called RatChet.
Here is the sample code of chat system I built using websocket:
You first need a server.php file:
<?php
require __DIR__ . '/vendor/autoload.php';
use Ratchet\Server\IoServer;
use Ratchet\Http\HttpServer;
use Ratchet\WebSocket\WsServer;
use App\MainHandler;
include_once("database.php");
// Create WebSocket server
$server = IoServer::factory(
new HttpServer(
new WsServer(
new MainHandler($conn)
)
),
8080
);
echo "WebSocket server started on ws://localhost:8080\n";
$server->run();
Then you need to create for clients to build connection with your server. In my case, it's webcoket.js:
const socket = new WebSocket(`ws://127.0.0.1:8080`);
let sender_id;
if(window.location.search !== ""){
sender_id = window.location.search.split("sender_id")[1].substring(1);
}
// Connection opened
socket.onopen = () => {
console.log("Connection established");
socket.send(JSON.stringify({
type : "establish_notifications",
sender_id : sender_id,
}));
console.log('WebSocket connection established for sender_id:', sender_id);
};
// Handle errors
socket.onerror = (error) => {
console.log('WebSocket error:', error);
};
// Handle connection close
socket.onclose = () => {
console.log('Connection closed');
};
export default socket;
I have built two features, live chats and live notification for those chats, and in Wsserver, you cann add only handler:
const socket = new WebSocket(`ws://127.0.0.1:8080`);
let sender_id;
if(window.location.search !== ""){
sender_id = window.location.search.split("sender_id")[1].substring(1);
}
// Connection opened
socket.onopen = () => {
console.log("Connection established");
socket.send(JSON.stringify({
type : "establish_notifications",
sender_id : sender_id,
}));
console.log('WebSocket connection established for sender_id:', sender_id);
};
// Handle errors
socket.onerror = (error) => {
console.log('WebSocket error:', error);
};
// Handle connection close
socket.onclose = () => {
console.log('Connection closed');
};
export default socket;
Here is my chat.php file:
<?php
namespace Library;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
class Chat implements MessageComponentInterface {
protected $clients;
protected $token;
protected $dbconn;
protected $chatTokens; // Store tokens and associated connections
public function __construct($dbconnection) {
$this->clients = new \SplObjectStorage;
$this->dbconn = $dbconnection;
$this->chatTokens = []; // Format: ['token' => [ConnectionInterface]]
}
public function onOpen(ConnectionInterface $wsconn) {
$this->clients->attach($wsconn);
echo "New connection! ({$wsconn->resourceId})\n";
}
public function onMessage(ConnectionInterface $wsconn, $msg) {
$data = json_decode($msg, true);
$sender_id = $data['sender_id'];
$receiver_id = $data['receiver_id'];
//GENERATE TOKEN OR GET TOKEN FROM DB
if($data['type'] === 'token'){
$select = "SELECT token FROM messages
WHERE (sender_id = '$sender_id' AND receiver_id = '$receiver_id')
OR (receiver_id = '$sender_id' AND sender_id = '$receiver_id')
LIMIT 1";
$result = mysqli_query($this->dbconn, $select);
if ($row = mysqli_fetch_assoc($result)) {
$this->token = $row['token'];
} else {
$this->token = $this->createChatToken();
// $this->token = $this->createChatToken();
// if(isset($this->chatTokens[$this->token])){
// $this->chatTokens[$this->token] = [];
// }
}
// if(!isset($this->chatTokens[$this->token])){
// $this->chatTokens[$this->token] = [];
// }
if (!isset($this->chatTokens[$this->token])) {
$this->chatTokens[$this->token] = [];
}
// Check if the connection already exists
if (!in_array($wsconn, $this->chatTokens[$this->token], true)) {
// Add the connection only if it's not already present
$this->chatTokens[$this->token][] = $wsconn;
}
// $this->chatTokens[$this->token][] = $wsconn;
// echo $this->token;
}
if($data['type'] === 'message' || !isset($data['type'])){
$message_text = $data['message_text'];
$insert = "INSERT INTO messages (sender_id, receiver_id, message_text, token) VALUES ('$sender_id', '$receiver_id', '$message_text', '$this->token')";
$mysqli_insert_query = mysqli_query($this->dbconn, $insert);
if($mysqli_insert_query){
echo "Inserted data into database";
}else{
echo "Could not insert into database";
}
// Route the message only to connections associated with the token
foreach ($this->chatTokens[$this->token] as $client) {
$client->send(json_encode([
'token' => $this->token,
'type' => 'message',
'sender_id' => $sender_id,
'receiver_id' => $receiver_id,
'message_text' => $message_text
]));
// echo "Data {$message_text} sent to {$receiver_id}";
}
}
}
public function onClose(ConnectionInterface $wsconn) {
// Detach connection
$this->clients->detach($wsconn);
foreach($this->chatTokens as $token => &$connections){
foreach($connections as $index => $connection){
if($connection === $wsconn){
unset($connections[$index]);
}
}
}
echo "Connection {$wsconn->resourceId} has disconnected\n";
}
public function onError(ConnectionInterface $wsconn, \Exception $e) {
echo "An error has occurred: {$e->getMessage()}\n";
$wsconn->close();
}
// Generate a unique token for a new chat session
public function createChatToken() {
$tok = bin2hex(random_bytes(16)); // Generate a secure random token
return $tok;
}
}
?>
Here is my notification.php file:
<?php
namespace Library;
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
include_once("send_email.php");
class Notification implements MessageComponentInterface{
protected $clients;
protected $NotificationToken;
protected $dbconn;
public function __construct($dbconnection){
$this->dbconn = $dbconnection;
$this->clients = [];
}
public function onOpen(ConnectionInterface $wsconn){
//EXTRACTED THE RECEIVER ID FROM URL
// $query = $wsconn->httpRequest->getUri()->getQuery();
// parse_str($query, $queryParams);
// $sender_id = $queryParams['sender_id']??null;
// $receiver_id = $queryParams['receiver_id']??null;
//SET THE CONNECTION IN CLIENTS
// if($sender_id && $receiver_id){
// $key = $sender_id.'_'.$receiver_id;
// $this->clients[$key] = [];
// }
// $this->clients[$key][] = $wsconn;
echo "Notification opened";
}
public function onMessage(ConnectionInterface $wsconn, $msg){
$data = json_decode($msg, true);
echo "Message data received! {$data['type']}";
if($data['type'] === 'establish_notifications'){
$sender_id = $data['sender_id'];
// if(!isset($this->clients[$sender_id])){
// $this->clients[$sender_id] = null;
// }
$this->clients[$sender_id] = $wsconn;
$wsconn->send(json_encode([
'type' => 'notification_established',
'message_text' => 'Notifications established for the sender'
]));
echo "Sender notification ID created!";
}
// $receiver_id = $data['receiver_id'];
// $sender_id = $data['sender_id'];
// $key = $receiver_id.'_'.$sender_id;
// $sender_receiver_key = $sender_id.'_'.$receiver_id;
// if(isset($this->clients[$sender_receiver_key])){
// $this->clients[$sender_receiver_key] = [];
// }
// $this->clients[$sender_receiver_key][] = $wsconn;
// $receiver_sender_key = $receiver_id.'_'.$sender_id;
if($data['type'] === 'notification'){
$receiver_id = $data['receiver_id'];
$sender_id = $data['sender_id'];
$message_text = $data['message_text'];
// if(isset($this->clients[$key])){
// if(isset($this->clients[$receiver_sender_key])){
// // foreach($this->clients[$key] as $client){
// foreach($this->clients[$receiver_sender_key] as $client){
// $client->send(json_encode([
// 'type' => 'notification',
// 'sender_id' => $sender_id,
// 'receiver_id' => $receiver_id,
// 'message_text' => $message_text
// ]));
// // echo "Notification: {$message_text}";
// }
// }
if(isset($this->clients[$receiver_id])){
// foreach($this->clients[$key] as $client){
// foreach($this->clients as $key => $client){
// if($key === $receiver_id){
$client =$this->clients[$receiver_id];
$client->send(json_encode([
'type' => 'notification',
'sender_id' => $sender_id,
'receiver_id' => $receiver_id,
'message_text' => $message_text
]));
//SELECT RECEIVER EMAIL FROM DB
$select = "SELECT email, full_name FROM users WHERE id = '$receiver_id'";
$mysqli_select_query = mysqli_query($this->dbconn, $select);
while($rows = mysqli_fetch_assoc($mysqli_select_query)){
$receiver_email = $rows['email'];
$receiver_full_name = $rows['full_name'];
}
$send_email = send_email("{$receiver_email}", "{$receiver_full_name}", "New Message Received", $message_text);
if($send_email){
echo "Email sent!";
}else{
echo "Could not send email!";
}
// }
// // echo "Notification: {$message_text}";
// }
}else{
echo "Receiver ID not found!";
}
}
}
public function onClose(ConnectionInterface $wsconn){
foreach ($this->clients as $id => $client) {
if ($client === $wsconn) {
// $this->clients[$id] = null;
}
}
}
public function onError(ConnectionInterface $wsconn, \Exception $e){
echo "onError: {$e->getMessage()}";
}
}
?>