I upgraded a PHP 7 application to PHP 8. The following code was working before, but no longer:
$options = [
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/x-www-form-urlencoded\r\n"
. 'Content-Length: ' . strlen($content),
'content' => $content,
'timeout' => 30,
],
];
$context = stream_context_create($options);
$stream = fopen($url, 'r', false, $context);
$read[] = $stream;
$write = null;
$except = null;
$streamsChanged = stream_select($read, $write, $except, 0, 50000);
Now the call to stream_select produces the following error:
Type: ValueError
Message: No stream arrays were passed
I've tried the same POST call using Insomnia without any issues, so it does appear to be related to how I'm using PHP 8.
A var_dump of $stream returns resource(stream), so the type seems correct. I also ran:
is_resource($stream)
&& get_resource_type($stream) === 'stream'
&& !feof($stream)
and it passed.
It is a known issue in PHP 8.x
In PHP 8.0+, the default protocol_version for an HTTP context changed to 1.1. HTTP/1.1 often uses Transfer-Encoding: chunked, which PHP implements internally as a filter, triggering this error when stream_select() is used.
One of the solutions is forcing the use of HTTP/1.0 in order to avoid the implicit chunked encoding filter.
For PHP , it is like:
'http' => [
'protocol_version' => '1.0',
// other parameters...
]
So, the following code will be fine:
<?php
$url="https://somedomain.com/index.php";
$content='test_data';
$options = [
'http' => [
'protocol_version' => '1.0',
'method' => 'POST',
'header' => "Content-Type: application/x-www-form-urlencoded\r\n"
. 'Content-Length: ' . strlen($content),
'content' => $content,
'timeout' => 30,
],
];
$context = stream_context_create($options);
$stream = fopen($url, 'r', false, $context);
if (is_resource($stream) && get_resource_type($stream) === 'stream' && !feof($stream)) {
// echo "ok";
}
$read[] = $stream;
$write = null;
$except = null;
$streamsChanged = stream_select($read, $write, $except, 0, 50000);
// echo $streamsChanged; (it may now return say 1)
?>
Apart from the above simple method, the following are other alternatives :