Integrating proc_open in PHP with JavaScript WebSockets involves using a long-running PHP script as a WebSocket server (using a library like Open Swoole or Ratchet) that then uses proc_open to manage separate, external processes. The output from proc_open is captured by the server-side PHP script and then pushed to the connected JavaScript client(s) via the WebSocket connection.
Directly connecting the JavaScript WebSocket to the pipes created by proc_open in a traditional, short-lived HTTP PHP script is not feasible because a standard PHP script terminates after the HTTP request finishes, closing all pipes. WebSockets require a persistent, dedicated connection.
Server-Side (PHP with Open Swoole)
You will need a dedicated PHP WebSocket server running continuously on its own port (e.g., 8080). This requires a PHP extension like Open Swoole.
server.php:
php
<?php
require __DIR__ . '/vendor/autoload.php';
use OpenSwoole\WebSocket\Server;
use OpenSwoole\Http\Request;
use OpenSwoole\Http\Response;
$server = new Server("0.0.0.0", 8080);
$server->on("Start", function (Server $server) {
echo "OpenSwoole WebSocket server started at http://0.0.0.0:8080\n";
});
$server->on("Open", function (Server $server, Request $request) {
echo "Connection open: {$request->fd}\n";
});
$server->on("Message", function (Server $server, \OpenSwoole\WebSocket\Frame $frame) {
// When a message is received from the JavaScript client, execute a command
if ($frame->data === "run_command") {
$cmd = "ls -l"; // Example command
$descriptorspec = array(
0 => array("pipe", "r"),
1 => array("pipe", "w"),
2 => array("pipe", "w")
);
$process = proc_open($cmd, $descriptorspec, $pipes);
if (is_resource($process)) {
// Read the output from the command
$output = stream_get_contents($pipes[1]);
fclose($pipes[1]);
proc_close($process);
// Send the output back to the specific client via WebSocket
$server->push($frame->fd, "Command Output: " . $output);
} else {
$server->push($frame->fd, "Failed to run command.");
}
}
});
$server->on("Close", function (Server $server, int $fd) {
echo "Connection close: {$fd}\n";
});
$server->start();
Run this server from your terminal: php server.php.
Client-Side (JavaScript with HTML)
The JavaScript client will connect to the running PHP WebSocket server using the WebSocket API.
index.html:
html
<!DOCTYPE html>
<html>
<head>
<title>PHP proc_open with WebSockets</title>
</head>
<body>
<h1>WebSocket Output</h1>
<button onclick="runCommand()">Run PHP Command</button>
<pre id="output"></pre>
<script>
const output = document.getElementById('output');
const socket = new WebSocket('ws://localhost:8080'); // Connect to your PHP server port
socket.addEventListener('open', function (event) {
output.textContent += 'CONNECTED\n';
});
socket.addEventListener('message', function (event) {
// Display message received from PHP server
output.textContent += 'Received: ' + event.data + '\n';
});
socket.addEventListener('error', function (event) {
output.textContent += 'ERROR\n';
});
function runCommand() {
if (socket.readyState === WebSocket.OPEN) {
socket.send('run_command'); // Send message to trigger command execution on server
output.textContent += 'Sent: run_command\n';
} else {
output.textContent += 'WebSocket is not open.\n';
}
}
</script>
</body>
</html>
Open index.html in your browser. When you click the button, JavaScript sends a message to the PHP WebSocket server, which executes proc_open and returns the output in real-time.