ฉันส่งเป็น POST ไปยังหน้า php ต่อไปนี้:
{a:1}
นี่คือเนื้อหาของคำขอ (คำขอ POST)
ใน php ฉันต้องทำอย่างไรเพื่อแยกค่านั้น
var_dump($_POST);
ไม่ใช่วิธีแก้ปัญหาไม่ทำงาน
ฉันส่งเป็น POST ไปยังหน้า php ต่อไปนี้:
{a:1}
นี่คือเนื้อหาของคำขอ (คำขอ POST)
ใน php ฉันต้องทำอย่างไรเพื่อแยกค่านั้น
var_dump($_POST);
ไม่ใช่วิธีแก้ปัญหาไม่ทำงาน
คำตอบ:
ในการเข้าถึงเอนทิตีของคำขอ POST หรือ PUT (หรือวิธี HTTP อื่น ๆ ):
$entityBody = file_get_contents('php://input');
นอกจากนี้STDIN
ค่าคงที่ยังเป็นสตรีมที่เปิดอยู่แล้วphp://input
ดังนั้นคุณสามารถทำสิ่งต่อไปนี้:
$entityBody = stream_get_contents(STDIN);
จากรายการคู่มือ PHP บนเอกสาร I / O สตรีม :
php: // inputเป็นสตรีมแบบอ่านอย่างเดียวที่ช่วยให้คุณอ่านข้อมูลดิบจากเนื้อความคำขอ ในกรณีของคำขอ POST คุณควรใช้php: // inputแทน
$HTTP_RAW_POST_DATA
เนื่องจากไม่ได้ขึ้นอยู่กับคำสั่ง php.ini พิเศษ ยิ่งไปกว่านั้นสำหรับกรณีเหล่านั้นที่$HTTP_RAW_POST_DATA
ไม่มีการเติมข้อมูลโดยค่าเริ่มต้นอาจเป็นทางเลือกที่ไม่จำเป็นต้องใช้หน่วยความจำมากนักในการเปิดใช้งาน always_populate_raw_post_data php: // inputไม่พร้อมใช้งานกับ enctype = "multipart / form-data"
โดยเฉพาะคุณจะต้องการที่จะทราบว่าphp://input
กระแสโดยไม่คำนึงถึงวิธีการที่คุณเข้าถึงได้ใน SAPI เว็บไม่ seekable ซึ่งหมายความว่าสามารถอ่านได้เพียงครั้งเดียว หากคุณกำลังทำงานในสภาพแวดล้อมที่มีการอัพโหลดเอนทิตี HTTP ขนาดใหญ่เป็นประจำคุณอาจต้องการรักษาอินพุตในรูปแบบสตรีม (แทนที่จะบัฟเฟอร์มันเหมือนตัวอย่างแรกด้านบน)
เพื่อรักษาทรัพยากรสตรีมบางอย่างเช่นนี้จะเป็นประโยชน์:
<?php
function detectRequestBody() {
$rawInput = fopen('php://input', 'r');
$tempStream = fopen('php://temp', 'r+');
stream_copy_to_stream($rawInput, $tempStream);
rewind($tempStream);
return $tempStream;
}
php://temp
ช่วยให้คุณจัดการปริมาณการใช้หน่วยความจำได้เนื่องจากมันจะสลับไปใช้พื้นที่เก็บข้อมูลของระบบแฟ้มอย่างโปร่งใสหลังจากเก็บข้อมูลจำนวนหนึ่ง (ค่าเริ่มต้น 2M) ขนาดนี้สามารถจัดการได้ในไฟล์ php.ini หรือต่อท้ายโดย/maxmemory:NN
ที่NN
จำนวนข้อมูลสูงสุดที่จะเก็บไว้ในหน่วยความจำก่อนที่จะใช้ไฟล์ชั่วคราวเป็นไบต์
แน่นอนเว้นแต่คุณจะมีเหตุผลที่ดีในการค้นหาอินพุทสตรีมคุณไม่จำเป็นต้องใช้ฟังก์ชั่นนี้ในเว็บแอปพลิเคชัน การอ่านตัวคำขอเอนทิตี HTTP ครั้งเดียวก็เพียงพอแล้วอย่าให้ลูกค้ารอทั้งวันในขณะที่แอปของคุณระบุว่าต้องทำอะไร
โปรดทราบว่าการป้อนข้อมูล php: // ไม่สามารถใช้ได้สำหรับคำขอที่ระบุContent-Type: multipart/form-data
ส่วนหัว ( enctype="multipart/form-data"
ในรูปแบบ HTML) นี่เป็นผลมาจาก PHP ได้แยกวิเคราะห์ข้อมูลฟอร์มลงใน$_POST
superglobal แล้ว
php://input
จะว่างเปล่าสำหรับapplication/x-www-form-urlencoded
ประเภทเนื้อหาเช่นกัน (นอกเหนือจากmultipart/form-data
)
php://input
เป็น ดังนั้นในขณะที่ (Fast) การกำหนดค่า CGI stream_get_contents(STDIN)
จะไม่ทำงานfile_get_contents("php://input")
ประสงค์
ส่งคืนค่าในอาร์เรย์
$data = json_decode(file_get_contents('php://input'), true);
$data
อาร์เรย์ที่เชื่อมโยงกันเพื่อตรวจสอบว่าแต่ละค่ามีการเข้ารหัสตามที่คุณต้องการหรือไม่ วิธีการ "สตรีมไปยังประเภทข้อมูล" ในการมองสิ่งต่าง ๆ อาจเป็นเรื่องง่าย แต่ก็อาจไม่ได้มีประสิทธิภาพเท่ากับการจัดการกับการเข้ารหัสใน "รูปแบบสตรีม" โดยใช้ตัวกรองสตรีม หากคุณไม่ได้จัดการปัญหาการเข้ารหัสและเพียงแค่ทำให้สะอาดและตรวจสอบความถูกต้องแสดงว่าคุณไม่มีขั้นตอน
เหตุผลที่เป็นไปได้สำหรับการว่าง$_POST
คือคำขอไม่ได้POST
หรือไม่POST
อีกต่อไป ... มันอาจเริ่มต้นจากการโพสต์ แต่พบ301
หรือ302
เปลี่ยนเส้นทางที่ไหนสักแห่งซึ่งเปลี่ยนเป็นGET
!
ตรวจสอบ$_SERVER['REQUEST_METHOD']
เพื่อตรวจสอบว่าเป็นกรณีนี้หรือไม่
ดูhttps://stackoverflow.com/a/19422232/109787สำหรับการอภิปรายที่ดีว่าทำไมเรื่องนี้ถึงไม่ควรเกิดขึ้น แต่ก็ยังทำได้
POST
GET
เมื่อฉันเพิ่ม a /
ท้าย URL ของฉันมันเริ่มแสดง POST แปลก!
ตรวจสอบ$HTTP_RAW_POST_DATA
ตัวแปร
php://input
ดิบ ไม่สามารถใช้ได้กับ$HTTP_RAW_POST_DATA
enctype="multipart/form-data"
หากคุณติดตั้งส่วนขยาย HTTP PECL คุณสามารถใช้http_get_request_body()
ฟังก์ชันเพื่อรับข้อมูลร่างกายเป็นสตริง
หากคุณติดตั้งส่วนขยายpecl / httpไว้คุณสามารถใช้ส่วนต่อไปนี้:
$request = new http\Env\Request();
$request->getBody();
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());
json_last_error() == JSON_ERROR_NONE
เป็นfalse
เช่นนั้นจะต้องส่งคืนอาร์เรย์ว่างเปล่า เกิดอะไรขึ้นถ้ามีคนส่ง XML หรือ YAML เพิ่มการทดสอบสำหรับประเภทเนื้อหาและไปจากที่นั่น
$_SERVER
superglobal สำหรับค่าที่เป็นประโยชน์ในการตรวจสอบ
http_get_request_body()
ทำขึ้นอย่างชัดเจนเพื่อรับเนื้อหาPUT
และPOST
คำขอตามเอกสารhttp://php.net/manual/fa/function.http-get-request-body.php
$_POST
superglobal นี่เป็นความจริง (โดยเฉพาะ) ในกรณีของคำขอ PUT เนื่องจาก PHP ไม่มี superglobal ที่เกี่ยวข้อง