Bagaimana cara mendapatkan tubuh POST di php?


273

Saya mengirimkan sebagai POST ke halaman php berikut ini:

{a:1}

Ini adalah badan permintaan (permintaan POST).
Dalam php, apa yang harus saya lakukan untuk mengekstraksi nilai itu?

var_dump($_POST); 

bukan solusinya, tidak bekerja.


23
Ini adalah pertanyaan yang bermanfaat bagi orang yang ingin membuat API RESTful. Sebagian besar tidak tahu cara mengakses data input mentah yang dikirim ke skrip mereka karena tidak tersedia melalui $_POSTsuperglobal. Ini juga (terutama) benar dalam kasus permintaan PUT, karena PHP tidak memiliki superglobal yang sesuai.
rdlowrey


1
Perlu dicatat bahwa nama $ _POST menyesatkan, karena tidak semua jenis data dari permintaan POST akan ada di sana, tetapi hanya ketika jenis kontennya adalah aplikasi / x-www-form-urlencoded atau multipart / form-data
Petruza

Jawaban:


549

Untuk mengakses badan entitas dari permintaan POST atau PUT (atau metode HTTP lainnya):

$entityBody = file_get_contents('php://input');

Selain itu, STDINkonstanta adalah aliran yang sudah terbuka php://input, sehingga Anda dapat melakukannya sebagai alternatif:

$entityBody = stream_get_contents(STDIN);

Dari entri manual PHP pada I / O streams docs :

php: // input adalah aliran hanya baca yang memungkinkan Anda membaca data mentah dari badan permintaan. Dalam hal permintaan POST, lebih baik menggunakan php: // input daripada $HTTP_RAW_POST_DATAtidak tergantung pada arahan khusus php.ini. Selain itu, untuk kasus-kasus di mana $HTTP_RAW_POST_DATAtidak diisi secara default, itu berpotensi alternatif yang kurang intensif memori untuk mengaktifkan always_populate_raw_post_data. php: // input tidak tersedia dengan enctype = "multipart / form-data".

Khususnya Anda ingin mencatat bahwa php://inputaliran, terlepas dari bagaimana Anda mengaksesnya di web SAPI, tidak dapat dicari . Ini berarti hanya dapat dibaca sekali. Jika Anda bekerja di lingkungan tempat entitas entitas HTTP besar diunggah secara rutin, Anda mungkin ingin mempertahankan input dalam bentuk alirannya (alih-alih buffering seperti contoh pertama di atas).

Untuk menjaga sumber daya aliran, sesuatu seperti ini dapat membantu:

<?php

function detectRequestBody() {
    $rawInput = fopen('php://input', 'r');
    $tempStream = fopen('php://temp', 'r+');
    stream_copy_to_stream($rawInput, $tempStream);
    rewind($tempStream);

    return $tempStream;
}

php://tempmemungkinkan Anda untuk mengelola konsumsi memori karena akan secara transparan beralih ke penyimpanan sistem file setelah sejumlah data disimpan (secara default 2M). Ukuran ini dapat dimanipulasi dalam file php.ini atau dengan menambahkan /maxmemory:NN, di mana NNjumlah maksimum data yang disimpan dalam memori sebelum menggunakan file sementara, dalam byte.

Tentu saja, kecuali Anda memiliki alasan yang sangat bagus untuk mencari di aliran input, Anda seharusnya tidak memerlukan fungsi ini dalam aplikasi web. Membaca badan entitas HTTP permintaan biasanya sudah cukup - jangan biarkan klien menunggu sepanjang hari sementara aplikasi Anda menentukan apa yang harus dilakukan.

Perhatikan bahwa php: // input tidak tersedia untuk permintaan yang menentukan Content-Type: multipart/form-dataheader ( enctype="multipart/form-data"dalam bentuk HTML). Ini hasil dari PHP sudah mem-parsing formulir data ke $_POSTsuperglobal.


17
Harap dicatat bahwa afaics, aliran STDIN tidak tersedia pada sistem yang menjalankan PHP menggunakan CGI, yaitu via mod_fcgid atau mod_fastcgi dll.
scy

tapi, saya meneruskan variabel (sebagai formulir-data) dengan permintaan, bagaimana saya bisa mengakses nilai yang ditentukan, saya melewati grant_type = kata sandi & nama pengguna = pengguna & kata sandi = lulus sebagai bentuk-data badan dengan permintaan, bagaimana saya akan mendapatkan hibah_type dari "$ entitasBody "
Anvar Pk

menurut pengujian saya, ini php://inputjuga kosong untuk application/x-www-form-urlencodedtipe konten (selain multipart/form-data)
YakovL

6
Untuk memperluas tanggapan @ scy: STDIN tidak tersedia, tetapi php://inputada. Jadi, sementara pada konfigurasi (Cepat) CGI stream_get_contents(STDIN)tidak akan berfungsi, file_get_contents("php://input")akan.
Sinus Mackowaty

16

mengembalikan nilai dalam array

 $data = json_decode(file_get_contents('php://input'), true);

Dalam skenario ini, Anda sekarang harus mengulang melalui $dataarray asosiatif untuk memeriksa apakah setiap nilai dikodekan sesuai keinginan Anda. Cara "stream-to-datatype" dalam melihat sesuatu mungkin sederhana, tetapi mungkin tidak seefisien berurusan dengan pengkodean dalam "bentuk aliran" menggunakan filter aliran. Jika Anda tidak menangani masalah penyandian dan hanya membersihkan dan memvalidasi, Anda kehilangan satu langkah.
Anthony Rutledge

13

Kemungkinan alasan untuk kosong $_POSTadalah bahwa permintaannya bukan POST, atau tidak POSTlagi ... Itu mungkin sudah dimulai sebagai pos, tetapi menemui 301atau 302mengarahkan ulang ke suatu tempat, yang dialihkan ke GET!

Periksa $_SERVER['REQUEST_METHOD']untuk memeriksa apakah ini masalahnya.

Lihat https://stackoverflow.com/a/19422232/109787 untuk diskusi yang baik tentang mengapa hal ini tidak boleh terjadi tetapi masih terjadi.


1
Pertanyaan ini diajukan dalam konteks pengembangan platform api REST.
Itay Moav -Malimovka

Saya tidak yakin apa yang Anda maksud? Api REST mungkin juga menemukan pengalihan di jalurnya, itulah masalah yang saya miliki.
Legolas

Maksud saya ketika saya mengajukan pertanyaan, saya tidak mencoba menyelesaikan bug, tetapi mencoba mencari tahu bagaimana mengembangkannya.
Itay Moav -Malimovka

3
petunjuk ini menyelamatkan hari saya. server penerima telah dikonfigurasi ulang untuk mengarahkan ulang ke https whoch memecahkan beberapa klien API.
DesertEagle

Sebenarnya permintaan saya adalah POSTtetapi setelah memeriksanya ternyata memang benar GET. Setelah saya menambahkan /di akhir URL saya, itu mulai menunjukkan POST. Aneh!
zackygaurav



2

Jika Anda menginstal ekstensi pecl / http , Anda juga dapat menggunakan ini:

$request = new http\Env\Request();
$request->getBody();

2
function getPost()
{
    if(!empty($_POST))
    {
        // when using application/x-www-form-urlencoded or multipart/form-data as the HTTP Content-Type in the request
        // NOTE: if this is the case and $_POST is empty, check the variables_order in php.ini! - it must contain the letter P
        return $_POST;
    }

    // when using application/json as the HTTP Content-Type in the request 
    $post = json_decode(file_get_contents('php://input'), true);
    if(json_last_error() == JSON_ERROR_NONE)
    {
        return $post;
    }

    return [];
}

print_r(getPost());

Yang sedikit hilang dari logika ini adalah pengujian nilai yang ditemukan di header Tipe Konten. Ini tidak berarti bahwa hanya karena $ _POST kosong yang JSON harus telah disampaikan, atau bahwa jika json_last_error() == JSON_ERROR_NONEadalah false, bahwa array kosong harus dikembalikan. Bagaimana jika seseorang telah mengirimkan XML atau YAML? Tambahkan tes untuk Tipe-Konten dan pergi dari sana.
Anthony Rutledge

Selain itu, metode permintaan HTTP dapat menjadi faktor dalam menentukan apakah Anda ingin menerima data input. Lihat $_SERVERsuperglobal untuk mengetahui nilai berguna.
Anthony Rutledge

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.