Encoding data into a WebSocket frame in PHP involves constructing the frame header and concatenating it with the payload data. This process adheres to the WebSocket Protocol (RFC 6455) specifications.
Here's a PHP function demonstrating how to encode data for a WebSocket frame:
Code

<?php

function encodeWebSocketFrame(string $payload, string $type = 'text', bool $masked = false): string
{
   $payloadLength = strlen($payload);
   $frame = '';

   // Set FIN bit and Opcode
   switch ($type) {
       case 'text':
           $b1 = 0x81; // FIN + Text frame (Opcode 0x1)
           break;
       case 'binary':
           $b1 = 0x82; // FIN + Binary frame (Opcode 0x2)
           break;
       case 'close':
           $b1 = 0x88; // FIN + Close frame (Opcode 0x8)
           break;
       case 'ping':
           $b1 = 0x89; // FIN + Ping frame (Opcode 0x9)
           break;
       case 'pong':
           $b1 = 0x8A; // FIN + Pong frame (Opcode 0xA)
           break;
       default:
           // Handle unknown types or throw an error
           return '';
   }
   $frame .= pack('C', $b1);

   // Set MASK bit and Payload Length
   $b2 = 0x00; // No mask by default for server-to-client frames
   if ($masked) {
       $b2 = 0x80; // Set MASK bit for client-to-server frames
   }

   if ($payloadLength <= 125) {
       $b2 |= $payloadLength;
       $frame .= pack('C', $b2);
   } elseif ($payloadLength > 125 && $payloadLength < 65536) {
       $b2 |= 126;
       $frame .= pack('C', $b2);
       $frame .= pack('n', $payloadLength); // Unsigned short (16-bit)
   } else { // $payloadLength >= 65536
       $b2 |= 127;
       $frame .= pack('C', $b2);
       $frame .= pack('J', $payloadLength); // Unsigned long long (64-bit)
   }

   // Add Masking Key if masked
   if ($masked) {
       $maskingKey = openssl_random_pseudo_bytes(4);
       $frame .= $maskingKey;
       // Apply mask to payload
       for ($i = 0; $i < $payloadLength; $i++) {
           $payload[$i] = $payload[$i] ^ $maskingKey[$i % 4];
       }
   }

   $frame .= $payload;

   return $frame;
}

// Example usage:
$message = "Hello, WebSocket!";
$encodedFrame = encodeWebSocketFrame($message, 'text');
echo $encodedFrame;

?>

Explanation:

   $b1 (First Byte):
       The most significant bit (MSB) is the FIN bit (set to 1 for the final frame of a message).
       The remaining bits represent the Opcode, indicating the frame type (e.g., text, binary, close, ping, pong).
   $b2 (Second Byte):
       The MSB is the MASK bit (set to 1 if the payload is masked, typically for client-to-server communication).
       The remaining bits indicate the Payload Length:
           If payloadLength <= 125, the length is encoded directly in these 7 bits.
           If payloadLength > 125 but < 65536, the value 126 is used, and the actual 16-bit length follows.
           If payloadLength >= 65536, the value 127 is used, and the actual 64-bit length follows.
   Masking Key (Optional):
       If masked is true, a 4-byte random masking key is generated and included in the frame.
       The payload data is then XORed with this masking key, byte by byte, before being appended to the frame.
   pack() Function:
       The pack() function is crucial for converting PHP data types into binary strings with specific formats (e.g., C for unsigned character, n for unsigned short, J for unsigned long long).

This function provides a foundational implementation for encoding data into WebSocket frames in PHP, allowing for communication with WebSocket clients or servers.