Polecono mi użyć tej metody php://input
zamiast $_POST
podczas interakcji z żądaniami Ajax z JQuery. To, czego nie rozumiem, to korzyści wynikające z zastosowania tego w porównaniu z globalną metodą $_POST
lub $_GET
.
Polecono mi użyć tej metody php://input
zamiast $_POST
podczas interakcji z żądaniami Ajax z JQuery. To, czego nie rozumiem, to korzyści wynikające z zastosowania tego w porównaniu z globalną metodą $_POST
lub $_GET
.
Odpowiedzi:
Powodem jest to, że php://input
zwraca wszystkie nieprzetworzone dane po nagłówkach HTTP żądania, niezależnie od typu zawartości.
Superglobal PHP ma$_POST
tylko zawijać dane, które są albo
application/x-www-form-urlencoded
(standardowy typ zawartości dla prostych formularzy) lubmultipart/form-data
(najczęściej używany do przesyłania plików)Jest tak, ponieważ są to jedyne typy treści, które muszą być obsługiwane przez programy klienckie . Tak więc serwer i PHP tradycyjnie nie oczekują żadnego innego rodzaju treści (co nie znaczy, że nie mogą).
Jeśli więc POST umieścisz stary, dobry HTML form
, żądanie wygląda mniej więcej tak:
POST /page.php HTTP/1.1
key1=value1&key2=value2&key3=value3
Ale jeśli dużo pracujesz z Ajaxem, ta probaby obejmuje również wymianę bardziej złożonych danych z typami (ciąg, int, bool) i strukturami (tablice, obiekty), więc w większości przypadków JSON jest najlepszym wyborem. Ale żądanie zawierające ładunek JSON wyglądałoby mniej więcej tak:
POST /page.php HTTP/1.1
{"key1":"value1","key2":"value2","key3":"value3"}
Zawartość byłaby teraz application/json
(lub przynajmniej żadna z wyżej wymienionych), więc PHP $_POST
-wrapper nie wie, jak sobie z tym poradzić (jeszcze).
Dane nadal tam są, po prostu nie można uzyskać do nich dostępu za pomocą opakowania. Więc musisz pobrać go sam w surowym formacie file_get_contents('php://input')
( o ile nie jest multipart/form-data
zakodowany ).
W ten sposób uzyskasz dostęp do danych XML lub dowolnego innego niestandardowego typu treści.
application/json
Jako prawidłowego źródła danych dla $_POST
tablicy. Są nawet opublikowane prośby o wsparcie.
php://input
może dać ci surowe bajty danych. Jest to przydatne, jeśli dane POSTed są strukturą zakodowaną w JSON, co często ma miejsce w przypadku żądania POST AJAX.
Oto funkcja, aby to zrobić:
/**
* Returns the JSON encoded POST data, if any, as an object.
*
* @return Object|null
*/
private function retrieveJsonPostData()
{
// get the raw POST data
$rawData = file_get_contents("php://input");
// this returns null if not valid json
return json_decode($rawData);
}
$_POST
Tablica jest bardziej użyteczny, gdy jesteś obsługi danych klucz-wartość z formularza, przedłożony przez tradycyjnego testu POST. Działa to tylko wtedy, gdy dane POSTed są zwykle w rozpoznawalnym formacie application/x-www-form-urlencoded
( szczegółowe informacje można znaleźć na stronie http://www.w3.org/TR/html4/interact/forms.html#h-17.13.4 ).
true
jako drugi parametr json_decode
, zwróci tablicę asocjacyjną.
Jeśli dane postu są zniekształcone, $ _POST nic nie będzie zawierało. Jednak wejście php: // będzie zawierało źle sformułowany ciąg.
Na przykład jest kilka aplikacji ajax, które nie tworzą prawidłowej sekwencji klucz-wartość dla przesłania pliku, i po prostu zrzucają cały plik jako dane postu, bez nazw zmiennych lub czegokolwiek. $ _POST będzie pusty, $ _FILES również pusty, a wejście php: // będzie zawierało dokładny plik zapisany jako ciąg znaków.
PHP nie zostało zaprojektowane tak, aby jawnie dać ci czysty interfejs REST (GET, POST, PUT, PATCH, DELETE) do obsługi żądań HTTP .
Jednakże $_POST
, $_GET
i $_FILES
Superglobale i funkcja filter_input_array()
są bardzo przydatne dla potrzeb przeciętnego człowieka / laika.
Główną ukrytą zaletą $_POST
(i $_GET
) jest to, że dane wejściowe są automatycznie kodowane automatycznie przez PHP . Nigdy nawet nie zastanawiasz się nad koniecznością zrobienia tego, szczególnie w przypadku parametrów ciągu zapytania w ramach standardowego żądania GET.
Biorąc to pod uwagę, w miarę pogłębiania wiedzy programistycznej i chęci korzystania z XmlHttpRequest
obiektu JavaScript (w niektórych przypadkach jQuery), pojawia się ograniczenie tego schematu.
$_POST
ogranicza użycie dwóch typów mediów w Content-Type
nagłówku HTTP :
application/x-www-form-urlencoded
, imultipart/form-data
Tak więc, jeśli chcesz wysłać wartości danych do PHP na serwerze i pokazać je w $_POST
superglobalu , musisz urlencode je po stronie klienta i wysłać te dane jako pary klucz / wartość - niewygodny krok dla nowicjuszy (szczególnie gdy próbujesz dowiedzieć się, czy różne części adresu URL wymagają różnych form urlencoding: normalny, surowy itp.).
Dla wszystkich użytkowników jQuery $.ajax()
metoda polega na konwersji JSON na pary klucz / wartość zakodowane w adresie URL przed przesłaniem ich na serwer. Możesz zmienić to zachowanie, ustawiając processData: false
. Po prostu przeczytaj dokumentację $ .ajax () i nie zapomnij wysłać poprawnego typu nośnika w nagłówku Content-Type.
Zazwyczaj, jeśli wykonujesz normalne, synchroniczne (gdy cała strona przerysowuje) żądania HTTP z formularzem HTML, agent użytkownika (przeglądarka internetowa) urlencode dla ciebie dane formularza. Jeśli chcesz wykonać asynchroniczne żądania HTTP przy użyciu XmlHttpRequest
obiektu, musisz zaprojektować ciąg znaków w postaci urlencod i wysłać go, jeśli chcesz, aby te dane $_POST
pojawiały się w superglobalu .
Konwersja z tablicy lub obiektu JavaScript na ciąg znaków zakodowany w trybie ciągłym przeszkadza wielu programistom (nawet w przypadku nowych interfejsów API, takich jak Form Data ). Woleliby po prostu wysłać JSON, a kod klienta byłby bardziej wydajny .
Pamiętaj (mrugnij, mrugnij), przeciętny twórca stron internetowych nie uczy się korzystać z XmlHttpRequest
obiektu bezpośrednio, funkcji globalnych, funkcji łańcuchowych, funkcji tablicowych i wyrażeń regularnych takich jak ty i ja ;-). Urlencoding to dla nich koszmar. ;-)
Brak intuicyjnej obsługi XML i JSON w PHP wyłącza wiele osób. Można by pomyśleć, że do tej pory będzie to część PHP (westchnienie).
XML, JSON i YAML mają typy multimediów, które można umieścić w Content-Type
nagłówku HTTP .
Sprawdź, ile typów mediów (wcześniej typów MIME) jest zdefiniowanych przez IANA.
Zobacz, ile jest nagłówków HTTP .
Korzystanie ze php://input
strumienia pozwala ominąć poziom abstrakcji dziecka siedzącego / trzymającego dłoń narzucony światu przez PHP. :-) Z dużą mocą przychodzi duża odpowiedzialność!
Teraz, zanim poradzisz sobie z wartościami danych przesyłanymi strumieniowo php://input
, powinieneś / musisz zrobić kilka rzeczy.
AH, HA! Tak, możesz chcieć, aby strumień danych przesyłany do Twojej aplikacji był kodowany w UTF-8, ale skąd możesz wiedzieć, czy tak jest, czy nie?
php://input
.Czy spróbujesz obsłużyć dane strumieniowe, nie wiedząc, ile najpierw? To okropny pomysł . Nie można polegać wyłącznie na Content-Length
nagłówku HTTP w celu uzyskania wskazówek na temat wielkości przesyłanych strumieniowo danych wejściowych, ponieważ mogą one zostać sfałszowane.
Będziesz potrzebować:
Czy spróbujesz przekonwertować dane strumienia na UTF-8, nie znając aktualnego kodowania strumienia? W jaki sposób? Filtr strumienia iconv ( przykład filtra strumienia iconv ) wydaje się potrzebować początkowego i końcowego kodowania, takiego jak ten.
'convert.iconv.ISO-8859-1/UTF-8'
Zatem jeśli jesteś sumienny, będziesz potrzebować:
( Aktualizacja : 'convert.iconv.UTF-8/UTF-8'
zmusi wszystko do UTF-8, ale nadal musisz wziąć pod uwagę znaki, których biblioteka iconv może nie wiedzieć, jak tłumaczyć. : 1) Wstaw fikcyjną postać, 2) Niepowodzenie / rzut i wyjątek).
Nie można polegać wyłącznie na Content-Encoding
nagłówku HTTP , ponieważ może to wskazywać na kompresję, jak poniżej. To nie jest to, z czego chcesz podjąć decyzję w odniesieniu do iconv.
Content-Encoding: gzip
Część I: Powiązane żądanie HTTP
Część II: Przesyłanie danych powiązanych
Część III: Powiązane typy danych
(Pamiętaj, że dane mogą nadal być ciągiem zakodowanym w adresie URL, który musisz następnie przeanalizować i zdekodować adres URL).
Część IV: Związane z wartością danych
Filtruj dane wejściowe.
Sprawdź poprawność danych wejściowych.
$_POST
Superglobalną wraz z php.ini ustawienia limitów na wejściu, są prostsze dla laika. Jednak obsługa kodowania znaków jest znacznie bardziej intuicyjna i wydajna podczas korzystania ze strumieni, ponieważ nie ma potrzeby przechodzenia przez superglobale (lub tablice, ogólnie), aby sprawdzić wartości wejściowe dla prawidłowego kodowania.
Napisałem więc funkcję, która pobierałaby dane POST z strumienia wejściowego php: // .
Tak więc wyzwaniem było przejście na metodę żądania PUT, DELETE LUB PATCH i nadal uzyskiwanie danych pocztowych wysłanych z tym żądaniem.
Dzielę się tym może dla kogoś z podobnym wyzwaniem. Oto funkcja, którą wymyśliłem i działa. Mam nadzieję, że to pomoże!
/**
* @method Post getPostData
* @return array
*
* Convert Content-Disposition to a post data
*/
function getPostData() : array
{
// @var string $input
$input = file_get_contents('php://input');
// continue if $_POST is empty
if (strlen($input) > 0 && count($_POST) == 0 || count($_POST) > 0) :
$postsize = "---".sha1(strlen($input))."---";
preg_match_all('/([-]{2,})([^\s]+)[\n|\s]{0,}/', $input, $match);
// update input
if (count($match) > 0) $input = preg_replace('/([-]{2,})([^\s]+)[\n|\s]{0,}/', '', $input);
// extract the content-disposition
preg_match_all("/(Content-Disposition: form-data; name=)+(.*)/m", $input, $matches);
// let's get the keys
if (count($matches) > 0 && count($matches[0]) > 0)
{
$keys = $matches[2];
foreach ($keys as $index => $key) :
$key = trim($key);
$key = preg_replace('/^["]/','',$key);
$key = preg_replace('/["]$/','',$key);
$key = preg_replace('/[\s]/','',$key);
$keys[$index] = $key;
endforeach;
$input = preg_replace("/(Content-Disposition: form-data; name=)+(.*)/m", $postsize, $input);
$input = preg_replace("/(Content-Length: )+([^\n]+)/im", '', $input);
// now let's get key value
$inputArr = explode($postsize, $input);
// @var array $values
$values = [];
foreach ($inputArr as $index => $val) :
$val = preg_replace('/[\n]/','',$val);
if (preg_match('/[\S]/', $val)) $values[$index] = trim($val);
endforeach;
// now combine the key to the values
$post = [];
// @var array $value
$value = [];
// update value
foreach ($values as $i => $val) $value[] = $val;
// push to post
foreach ($keys as $x => $key) $post[$key] = isset($value[$x]) ? $value[$x] : '';
if (is_array($post)) :
$newPost = [];
foreach ($post as $key => $val) :
if (preg_match('/[\[]/', $key)) :
$k = substr($key, 0, strpos($key, '['));
$child = substr($key, strpos($key, '['));
$child = preg_replace('/[\[|\]]/','', $child);
$newPost[$k][$child] = $val;
else:
$newPost[$key] = $val;
endif;
endforeach;
$_POST = count($newPost) > 0 ? $newPost : $post;
endif;
}
endif;
// return post array
return $_POST;
}
Prosty przykład tego, jak z niego korzystać
<?php
if(!isset($_POST) || empty($_POST)) {
?>
<form name="form1" method="post" action="">
<input type="text" name="textfield"><br />
<input type="submit" name="Submit" value="submit">
</form>
<?php
} else {
$example = file_get_contents("php://input");
echo $example; }
?>