Php bir POST gövdesi almak nasıl?


273

Ben bir php sayfasına POST olarak aşağıdaki gönderir:

{a:1}

Bu, isteğin gövdesidir (POST isteği).
Php, bu değeri ayıklamak için ne yapmam gerekir?

var_dump($_POST); 

çözüm değil, çalışmıyor.


23
Bu, RESTful API'ler oluşturmak isteyen kişiler için yararlı bir sorudur. Çoğu, $_POSTsüper küresel aracılığıyla mevcut olmadığından komut dosyalarına gönderilen ham girdi verilerine nasıl erişeceğini bilmiyor . PHP'nin karşılık gelen bir süper küresel olmadığı için bu PUT isteklerinde de (özellikle) doğrudur.
rdlowrey


1
$ _POST adının yanıltıcı olduğunu belirtmek gerekir , çünkü bir POST isteğinden herhangi bir veri türü olmayacaktır, ancak yalnızca içerik türü application / x-www-form-urlencoded veya multipart / form-data olduğunda
Petruza

Yanıtlar:


549

POST veya PUT isteğinin varlık gövdesine (veya başka bir HTTP yöntemine) erişmek için:

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

Ayrıca, STDINsabit zaten açık bir akıştır php://input, böylece alternatif olarak şunları yapabilirsiniz:

$entityBody = stream_get_contents(STDIN);

Gönderen I PHP manuel giriş / Ç akışları docs :

php: // input , istek gövdesinden ham verileri okumanızı sağlayan salt okunur bir akıştır. POST istekleri halinde, bu kullanım tercih edilir php: // input yerine $HTTP_RAW_POST_DATAözel php.ini yönergelerinin bağlı değildir olarak. Ayrıca, $HTTP_RAW_POST_DATAvarsayılan olarak doldurulmadığı durumlarda , always_populate_raw_post_data işlevini etkinleştirmek için daha az bellek yoğun bir alternatiftir. php: // input , enctype = "multipart / form-data" ile kullanılamaz.

Özellikle sen dikkat isteyeceksiniz php://inputakışı, ne olursa olsun bir web SAPI'de erişmek nasıl, aranabilir durumda . Bu, yalnızca bir kez okunabileceği anlamına gelir. Büyük HTTP varlık gövdelerinin rutin olarak yüklendiği bir ortamda çalışıyorsanız, girdiyi akış formunda (yukarıdaki ilk örnek gibi arabelleğe almak yerine) korumak isteyebilirsiniz.

Akış kaynağını korumak için böyle bir şey yardımcı olabilir:

<?php

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

    return $tempStream;
}

php://tempbellek tüketimini yönetmenize izin verir, çünkü belirli miktarda veri saklandıktan sonra şeffaf bir şekilde dosya sistemi depolamasına geçer (varsayılan olarak 2M). Bu boyut php.ini dosyasında veya ekleyerek manipüle edilebilir /maxmemory:NNnerede, NNbayt olarak, geçici bir dosya kullanmadan önce hafızada tutmak için maksimum veri miktarıdır.

Tabii ki, giriş akışında arama yapmak için gerçekten iyi bir nedeniniz yoksa, bir web uygulamasında bu işlevselliğe ihtiyacınız olmamalıdır. HTTP isteği varlık gövdesini bir kez okumak genellikle yeterlidir; uygulamanız ne yapacağınızı anlarken müşterilerinizi tüm gün bekletmeyin.

Content-Type: multipart/form-dataÜstbilgi belirten istekler için php: // girişinin kullanılamadığını unutmayın ( enctype="multipart/form-data"HTML formlarında). Bu, PHP'nin form verilerini $_POSTsüper küresel olarak ayrıştırmış olmasından kaynaklanır .


17
O afaics unutmayınız, STDIN akışı, yani aracılığıyla mod_fcgid veya mod_fastcgi vb PHP kullanarak CGI çalıştıran sistemlerde kullanılamaz
scy

ancak, istekle değişken (form-data olarak) geçiyorum, belirtilen değere nasıl erişebilirim, grant_type = password & username = user & password = istekle form-veri gövdesi olarak geçiyorum, nasıl "$" dan grant_type geçireceğim entityBody "
Anvar Pk

php://inputapplication/x-www-form-urlencodedmultipart/form-data
testime

6
@ Scy'nin cevabını genişletmek için: STDIN mevcut değil, fakat php://inputmevcut. Bu yüzden (Hızlı) CGI yapılandırmaları stream_get_contents(STDIN)çalışmazken file_get_contents("php://input")çalışacaktır.
Sinus Mackowaty

16

dizideki değeri döndür

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

Bu senaryoda, artık $dataher bir değerin istediğiniz şekilde kodlanıp kodlanmadığını kontrol etmek için ilişkilendirilebilir dizi arasında döngü yapmanız gerekir . Olaylara "akış-veri tipi" yolu basit olabilir, ancak bir akış filtresi kullanarak "akış formunda" kodlama ile uğraşmak kadar etkili olmayabilir. Kodlama sorunlarını ele almıyorsanız ve sadece sterilize edip onaylıyorsanız, bir adımı kaçırıyorsunuz demektir.
Anthony Rutledge

13

Boşluğun olası bir nedeni $_POST, isteğin artık olmaması POSTveya POSTartık olmamasıdır ... Posta olarak başlamış olabilir, ancak bir yere yönlendirilmiş 301veya bir 302yere yönlendirilmiş olabilir GET!

Durumun $_SERVER['REQUEST_METHOD']bu olup olmadığını kontrol edin .

Bunun neden olmasa da hala olması gerektiği konusunda iyi bir tartışma için bkz. Https://stackoverflow.com/a/19422232/109787 .


1
Bu soru bir REST api platformu geliştirme bağlamında soruldu.
Itay Moav -Malimovka

Ne anlatmak istediğinden emin değilim? Bir REST api de yolunda yönlendirmeler bulabilir, bu benim sorunumdu.
Legolas

Demek istediğim, soruyu sorduğumda, bir hatayı çözmeye çalışmıyordum, daha ziyade nasıl geliştirileceğini anlamaya çalışıyordum.
Itay Moav -Malimovka

3
bu ipucu günümü kurtardı. alıcı sunucu, bazı API istemcilerini bozan https'ye yönlendirmek üzere yeniden yapılandırıldı.
DesertEagle

Aslında benim isteğim, POSTancak inceledikten sonra bunun olduğunu gösteriyordu GET. URL'imin /sonuna a ekledikten sonra POST gösterilmeye başlandı. Tuhaf!
zackygaurav



2

Eğer varsa pecl / http uzantı yüklü, ayrıca bu kullanabilirsiniz:

$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());

Bu mantık bitinin eksik olduğu, İçerik Türü başlığında bulunan değerin testidir. $ _POST JSON sunulmuş olması gerektiğini boştur, ya eğer bu sadece çünkü anlamına gelmez json_last_error() == JSON_ERROR_NONEolduğunu false, boş bir dizi döner gerektiğini. Birisi XML veya YAML gönderdiyse ne olur? İçerik Türü için bir test ekleyin ve oradan gidin.
Anthony Rutledge

Ayrıca, HTTP istek yöntemi giriş verilerini kabul etmek isteyip istemediğinizi belirlemede etkili olabilir. $_SERVERKontrol edilecek faydalı değerler için süper küresel olana bakınız .
Anthony Rutledge

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.