<?php
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$STDIN = fopen("/tmp/some-named-pipe", "r");
$STDOUT = fopen("/tmp/foo.out", "wb");
$STDERR = fopen("/tmp/foo.err", "wb");
echo "Hello, World!"; // goes to /tmp/foo.out, implied STDOUT
fscanf($STDIN, "%s\n", $top_secret); // explicit $STDIN, cant use STDIN
?>
Run Code Online (Sandbox Code Playgroud)
为什么重定向到新STDOUT隐式工作,但是新STDIN的重定向必须明确地发生?
原始的STDIN,STDOUT和STDERR是PHP中的系统常量.它们在PHP初始化时填充了标准输入,输出和错误的文件描述符资源.
php.net文档描述了有关常量资源的以下内容:
常数的值; 只允许标量和空值.标量值是整数,浮点数,字符串或布尔值.可以定义资源常量,但不建议这样做,并且可能导致不可预测的行为.
当fclose(STDOUT)被调用时,文件描述符资源被关闭,并从STDOUT不断脱落.与常量的默认行为相反,STDOUT常量会发生变化.
当字符串被回显时echo "Hello, World!",PHP将不使用STDOUT常量,但它将从操作系统实时查询当前的"标准输出"文件描述符.而且,STDOUT常量本身一旦被fclose'd就会变得无法使用.即使如下语句fwrite(STDOUT, "hello")将无法正常工作.
为标准输出配置新的文件描述符时,可以方便地输入新的文件描述符$STDOUT.请注意,这是一个变量而不是常量.根据定义,不可能在PHP中重新定义常量,系统常量STDOUT在这里也不例外.目前无法将新文件描述符重新分配给STDOUT常量.
最后,为了使这项工作更直观,PHP团队应该考虑使用便利函数来重新分配这些文件描述符,或者至少使系统常量更像"魔术常量",因为它们会自动评估实际的文件描述符.