Search code examples
stdinphp

Non-blocking on STDIN in PHP CLI


Is there anyway to read from STDIN with PHP that is non blocking:

I tried this:

stream_set_blocking(STDIN, false);
echo fread(STDIN, 1);

and this:

$stdin = fopen('php://stdin', 'r');
stream_set_blocking($stdin, false);
echo 'Press enter to force run command...' . PHP_EOL;
echo fread($stdin, 1);

but it still blocks until fread gets some data.

I noticed a few open bug reports about this (7 years old), so if it can't be done, does any one know any crude hacks that could accomplish this (on Windows and Linux)?


Solution

  • Here's what I could come up with. It works fine in Linux, but on Windows, as soon as I hit a key, the input is buffered until enter is pressed. I don't know a way to disable buffering on a stream.

    <?php
    
    function non_block_read($fd, &$data) {
        $read = array($fd);
        $write = array();
        $except = array();
        $result = stream_select($read, $write, $except, 0);
        if($result === false) throw new Exception('stream_select failed');
        if($result === 0) return false;
        $data = stream_get_line($fd, 1);
        return true;
    }
    
    while(1) {
        $x = "";
        if(non_block_read(STDIN, $x)) {
            echo "Input: " . $x . "\n";
            // handle your input here
        } else {
            echo ".";
            // perform your processing here
        }
    }
    
    ?>