Przy ilości wyjątków i braku możliwości przenoszenia przy użyciu php://input
, polecam przeczytanie strumienia i zapisanie go w innym strumieniu, aby uniknąć nieoczekiwanego zachowania.
Można użyć php://memory
aby utworzyć plik-stream-jak opakowanie, które daje wszystkie te same funkcje, które php://input
powinien mieć bez wszystkich irytujących zachowań.
Przykład:
<?php
$inputHandle = fopen('php://memory', 'r+');
fwrite($inputHandle, file_get_contents('php://input'));
fseek($inputHandle, 0);
Dodatkowo można stworzyć własną klasę odnieść się do tego obiektu konsekwentnie:
<?php
class InputReader {
private static $instance;
/**
* Factory for InputReader
*
* @param string $inputContents
*
* @return InputReader
*/
public static function instance($inputContents = null) {
if (self::$instance === null) {
self::$instance = new InputReader($inputContents);
}
return self::$instance;
}
protected $handle;
/**
* InputReader constructor.
*
* @param string $inputContents
*/
public function __construct($inputContents = null) {
// Open up a new memory handle
$this->handle = fopen('php://memory', 'r+');
// If we haven't specified the input contents (in case you're reading it from somewhere else like a framework), then we'll read it again
if ($inputContents === null) {
$inputContents = file_get_contents('php://input');
}
// Write all the contents of php://input to our memory handle
fwrite($this->handle, $inputContents);
// Seek back to the start if we're reading anything
fseek($this->handle, 0);
}
public function getHandle() {
return $this->handle;
}
/**
* Wrapper for fseek
*
* @param int $offset
* @param int $whence
*
* @return InputReader
*
* @throws \Exception
*/
public function seek($offset, $whence = SEEK_SET) {
if (fseek($this->handle, $offset, $whence) !== 0) {
throw new \Exception('Could not use fseek on memory handle');
}
return $this;
}
public function read($length) {
$read = fread($this->handle, $length);
if ($read === false) {
throw new \Exception('Could not use fread on memory handle');
}
return $read;
}
public function readAll($buffer = 8192) {
$reader = '';
$this->seek(0); // make sure we start by seeking to offset 0
while (!$this->eof()) {
$reader .= $this->read($buffer);
}
return $reader;
}
public function eof() {
return feof($this->handle);
}
}
Zastosowanie:
$first1024Bytes = InputReader::instance()->seek(0)->read(1024);
$next1024Bytes = InputReader::instance()->read(1024);
Usage (czytaj całość):
$phpInput = InputReader::instance()->readAll();
Z kwoty wyjątków w instrukcji oraz brak przenośności, polecam po prostu zapisując wynik po przeczytaniu go po raz pierwszy. Po tym możesz szukać jak najwięcej z wynikiem (i nie musisz zapisywać go w pliku - php: // memory powinno to zrobić.) – h2ooooooo
@ h2ooooooo dziękuję, zrezygnowałem z "naprawy" "ten problem i zakończył się planem uniknięcia więcej niż jednego wejścia do czytania we wszystkich przyszłych projektach minowych, jak sugerowałeś. Jeśli skonwertujesz swój komentarz na odpowiedź, zaakceptuję to. – gseric
Nie ma za co - daj mi sekundę, a ja będę miał odpowiedź. – h2ooooooo