2

ドキュメントに従って、常にphp://inputHTTP 要求本文が含まれているとは限りません。

スクリプトの開始時に常にストリームを開き、ユーザー アプリケーションで利用できるようにするコードがいくつかあります。

$stream = fopen('php://input', 'rb');

ユーザー アプリケーションが空のストリームから読み取ろうとするとContent-Length > 0、ライブラリに例外をスローさせたい:

リクエストボディは利用できません。

私の問題は次のとおりです。

  • ストリームが空の場合、呼び出されていないときにfeof()戻ります。falsefread()
  • このストリームはシークをサポートしていないため、fread()1 バイトはできません。fseek()
  • 別のストリームを開いphp://inputて事前に読み取ろうとすることはできません。これは、このストリームが複数回利用可能であることに依存できないためです。
  • パフォーマンス上の理由から、ユーザー アプリケーションに手を渡す前にやみくもにコピーphp://inputしたくありません。php://temp

その結果、 の直後にデータが含まれているかどうかを判断することは可能ですかphp://inputfopen()fread()?

4

2 に答える 2

2

私が見つけた解決策は、リクエスト本文を表すクラスを作成し、php://input直接ではなくこのクラスから読み取ることです。

class RequestBody
{
    protected $firstByte;

    protected $isEmpty;

    public function __construct($stream)
    {
        $this->firstByte = fread($stream, 1);
        $this->isEmpty = ($this->firstByte === '');

        // ...
    }

    public function isEmpty()
    {
        return $this->isEmpty;
    }

    public function read($length)
    {
        // ...
    }
}

$body = new RequestBody(fopen('php://input', 'rb'));

クラス コンストラクターは、ストリームの最初のバイトを読み取り、後で使用するために格納し、ストリームが空かどうかを即座に認識します。

read()$length - 1最初に呼び出されたときに最初のバイト + バイトを返すことにより、この複雑さを隠します。

于 2012-08-09T09:02:53.857 に答える
0

「php://inputで開かれたストリームは一度しか読み取ることができません。ストリームはシーク操作をサポートしていません。」

http://php.net/manual/en/wrappers.php.php

私にとって、これはそれが昔ながらの読み取り専用ストリームであることを示唆しています。ファイルの終わりなのか長さなのかを調べてテストすることはできません。

于 2012-07-02T21:57:51.417 に答える