2

I'm writing a PHP script and I would like to be able to optionally use a file as the script input. This way:

$ php script.php < file.txt

I'm, actually, able to do that using file_get_contents:

$data = file_get_contents('php://stdin');

However, if I don't pass a file to the input, the scripts hangs indefinetelly, waiting for an input.

I tried the following, but it didn't work:

$data = '';
$in = fopen('php://stdin', 'r');
do {
    $bytes = fread($in, 4096);
    // Maybe the input will be empty here?! But no, it's not :(
    if (empty($bytes)) {
        break;
    }
    $data .= $bytes;
} while (!feof($in));

The script waits for fread to return a value, but it never returns. I guess it waits for some input the same way file_get_contents does.

Another attempt was made by replacing the do { ... } while loop by a while { ... }, checking for the EOF before than trying to read the input. But that also didn't work.

Any ideas on how can I achieve that?

2
  • @JustOnUnderMillions maybe I'm asking too much from PHP client, but there are other non-PHP command-line programs that implement this logic – reads the input or ignores/exits. Commented Apr 7, 2017 at 14:18
  • yep, you are right. I was on the wrong lane. @Alex Howansky gots it. Commented Apr 7, 2017 at 14:20

1 Answer 1

3

You can set STDIN to be non-blocking via the stream_set_blocking() function.

function stdin()
{
    $stdin = '';
    $fh = fopen('php://stdin', 'r');
    stream_set_blocking($fh, false);
    while (($line = fgets($fh)) !== false) {
        $stdin .= $line;
    }
    return $stdin;
}

$stdin = stdin(); // returns the contents of STDIN or empty string if nothing is ready

Obviously, you can change the use of line-at-a-time fgets() to hunk-at-a-time fread() as per your needs.

Sign up to request clarification or add additional context in comments.

3 Comments

as i understood from the OP , i think it's not about blocking IO , it's about checking the input if isset or not , 'However, if I don't pass a file to the input, the scripts hangs indefinetelly, waiting for an input.'
Right -- this technique will alleviate that issue. If no input is available on STDIN, this function will immediately return an empty string.
@AlexHowansky, it worked the way I wanted. I didn't know about stream_set_blocking function.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.