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.
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:
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://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.
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.
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.
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!
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 Preturn $_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.
$_POST
superglobal. Ini juga (terutama) benar dalam kasus permintaan PUT, karena PHP tidak memiliki superglobal yang sesuai.Jawaban:
Untuk mengakses badan entitas dari permintaan POST atau PUT (atau metode HTTP lainnya):
Selain itu,
STDIN
konstanta adalah aliran yang sudah terbukaphp://input
, sehingga Anda dapat melakukannya sebagai alternatif:Dari entri manual PHP pada I / O streams docs :
Khususnya Anda ingin mencatat bahwa
php://input
aliran, 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://temp
memungkinkan 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 manaNN
jumlah 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-data
header (enctype="multipart/form-data"
dalam bentuk HTML). Ini hasil dari PHP sudah mem-parsing formulir data ke$_POST
superglobal.sumber
php://input
juga kosong untukapplication/x-www-form-urlencoded
tipe konten (selainmultipart/form-data
)php://input
ada. Jadi, sementara pada konfigurasi (Cepat) CGIstream_get_contents(STDIN)
tidak akan berfungsi,file_get_contents("php://input")
akan.mengembalikan nilai dalam array
sumber
$data
array 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.Kemungkinan alasan untuk kosong
$_POST
adalah bahwa permintaannya bukanPOST
, atau tidakPOST
lagi ... Itu mungkin sudah dimulai sebagai pos, tetapi menemui301
atau302
mengarahkan ulang ke suatu tempat, yang dialihkan keGET
!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.
sumber
POST
tetapi setelah memeriksanya ternyata memang benarGET
. Setelah saya menambahkan/
di akhir URL saya, itu mulai menunjukkan POST. Aneh!Periksa
$HTTP_RAW_POST_DATA
variabelnyasumber
php://input
.$HTTP_RAW_POST_DATA
tidak tersedia denganenctype="multipart/form-data"
.Jika Anda telah menginstal ekstensi HTTP PECL, Anda dapat menggunakan
http_get_request_body()
fungsi ini untuk mendapatkan data tubuh sebagai string.sumber
Jika Anda menginstal ekstensi pecl / http , Anda juga dapat menggunakan ini:
sumber
sumber
json_last_error() == JSON_ERROR_NONE
adalahfalse
, bahwa array kosong harus dikembalikan. Bagaimana jika seseorang telah mengirimkan XML atau YAML? Tambahkan tes untuk Tipe-Konten dan pergi dari sana.$_SERVER
superglobal untuk mengetahui nilai berguna.http_get_request_body()
secara eksplisit dibuat untuk mendapatkan tubuhPUT
danPOST
permintaan sesuai dokumentasi http://php.net/manual/fa/function.http-get-request-body.phpsumber