71

I know PHP is usually used for web development, where there is no standard input, but PHP claims to be usable as a general-purpose scripting language, if you do follow it's funky web-based conventions. I know that PHP prints to stdout (or whatever you want to call it) with print and echo, which is simple enough, but I'm wondering how a PHP script might get input from stdin (specifically with fgetc(), but any input function is good), or is this even possible?

Chris Lutz
  • 73,191
  • 16
  • 130
  • 183

10 Answers10

93

It is possible to read the stdin by creating a file handle to php://stdin and then read from it with fgets() for a line for example (or, as you already stated, fgetc() for a single character):

<?php
$f = fopen( 'php://stdin', 'r' );

while( $line = fgets( $f ) ) {
  echo $line;
}

fclose( $f );
?>
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
Patrick Glandien
  • 7,791
  • 5
  • 41
  • 47
48

Reading from STDIN is recommended way

<?php
while (FALSE !== ($line = fgets(STDIN))) {
   echo $line;
}
?>
anatoly techtonik
  • 19,847
  • 9
  • 124
  • 140
26

To avoid having to mess around with filehandles, use file_get_contents() and php://stdin:

$ echo 'Hello, World!' | php -r 'echo file_get_contents("php://stdin");'
Hello, World!

(If you're reading a truly huge amount of data from stdin you might want to use the filehandle approach, but this should be good for many megabytes.)

mjs
  • 63,493
  • 27
  • 91
  • 122
  • That will block the script and the web server indefinitely! Use `file_get_contents('php://input')` instead, that works. – ygoe Apr 04 '23 at 21:07
17

A simple method is

$var = trim(fgets(STDIN));
Muhammad Usman
  • 10,426
  • 22
  • 72
  • 107
13

Grab it all in one shot:

$contents = file_get_contents("php://stdin");
echo $contents;
redolent
  • 4,159
  • 5
  • 37
  • 47
  • That will block the script and the web server indefinitely! Use `file_get_contents('php://input')` instead, that works. – ygoe Apr 04 '23 at 21:07
8

You can use fopen() on php://stdin:

$f = fopen('php://stdin', 'r');
Greg
  • 316,276
  • 54
  • 369
  • 333
6

This also works:

$data = stream_get_contents(STDIN);
Andy
  • 49,085
  • 60
  • 166
  • 233
Richard Cross
  • 396
  • 3
  • 12
5

When using fgets, it may block in bash scripts, if the stdin isn't set or empty, including while using the @ php error control operator.

#!/usr/bin/php
<?php
$pipe = @trim(fgets(STDIN));
// Script was called with an empty stdin
// Fail to continue, php warning 

This behavior can be avoided by setting stream_set_blocking on the php header:

#!/usr/bin/php
<?php
stream_set_blocking(STDIN, false);
$pipe = @trim(fgets(STDIN));
// Script was called with an empty stdin
// No errors or warnings, continue 
echo $pipe . "!";

As example, to be called as follow:

echo "Hello world" | ./myPHPscript
// Output "Hello world!"
./myPHPscript
// Output "!"
NVRM
  • 11,480
  • 1
  • 88
  • 87
  • 1
    When using the `declare(strict_types=1);` instruction, it is worth noting that setting the second parameter of `stream_set_blocking` to `0` will cause an error as this function expects its second parameter to be a valid boolean value, when providing an integer. Use `stream_set_blocking(STDIN, false);` instead. – Amin NAIRI Aug 07 '19 at 17:42
5

IIRC, you may also use the following:

$in = fopen(STDIN, "r");
$out = fopen(STDOUT, "w");

Technically the same, but a little cleaner syntax-wise.

Fritz H
  • 3,539
  • 2
  • 26
  • 37
1

Instead of manually opening STDIN stream, use built in readline() function if you just want to read a single line without too much a hassle :

<?php
$age= readline("Enter your age: ");
echo "Your age is : ".$age;

PHP documentation is your friend : https://www.php.net/manual/en/function.readline.php

Donovan P
  • 591
  • 5
  • 9