Post data in PHP captured in the $_POST and $_FILES super-globals, however if you are dealing with PATCH or PUT method we can’t depend $_POST superglobal. For this PHP 8.4 introduced the request_parse_body() function.
In PHP the $_POST superglobal store the post data when user submit data using the post Http verb. However if you are sending data using ajax or sending data to a REST api, you may use other http methods like PUT, PATCH and DELETE. In PHP to capture such data we tend to use php://input stream wrapper:
Prior to PHP 8.4:
$post = file_get_contents("php://input");
With PHP 8.4 the request_parse_body() function introduced to manipulate non-post http verbs.
[$_POST, $_FILES] = request_parse_body();
request_parse_body() return an array where the item at index 0 contain the $_POST data while item at index 1 contain the $_FILES data if any.
request_parse_body() reads the request body and parses it according to the Content-Type header. Currently, two content types are supported: application/x-www-form-urlencoded and multipart/form-data
An example ajax request:
request_parse_body_demo.php
<html>
<head>
<meta charset="utf-8" />
<title>Request parse body demo</title>
</head>
<body>
<form method="post" action="#" enctype="multipart/form-data">
<p>
<label>Title</label>
<input type="text" name="title" />
</p>
<p>
<label>Content</label>
<textarea name="content"></textarea>
</p>
<p>
<label>Select image</label>
<input type="file" name="image" />
</p>
<p>
<button type="submit" name="submit" id="submit">Submit</button>
</p>
</form>
<script type="text/javascript">
document.querySelector("#submit").addEventListener("click", async function (e) {
e.preventDefault();
const formData = new FormData();
formData.append('title', document.querySelector("input[name=title]").value);
formData.append('content', document.querySelector("textarea[name=content]").value);
// image
formData.append('image', document.querySelector("input[name=image]").files[0]);
const response = await fetch("./api.php", {
method: "PUT",
body: formData,
});
console.log(await response.json());
});
</script>
</body>
</html>
In this script we have a simple form that when submitted it makes ajax request to the server using javascript fetch Api. In the fetch() function i specified the url to send the data which is “api.php” and specified the method which is PUT in this case and the body in the form of formData object.
api.php
<?php
var_dump($_POST, $_FILES);
?>
If you run this example and checked the result of dumping the $_POST and $_FILES you will get empty arrays as we are using PUT as the method type in the fetch request
array(0) { } array(0) { }
Using request_parse_body():
api.php
<?php
try {
[$_POST, $_FILES] = request_parse_body();
var_dump($_POST, $_FILES);
} catch(RequestParseBodyException) {
echo "empty post data";
}
?>
Now by checking the $_POST and $_FILES you will see the dumped data:
array(2) { ["title"]=> string(10) "post title" ["content"]=> string(12) "post content" } array(1) { ["image"]=> array(6) { ["name"]=> string(22) "111473537-240x180.webp" ["full_path"]=> string(22) "111473537-240x180.webp" ["type"]=> string(10) "image/webp" ["tmp_name"]=> string(27) "C:\Windows\Temp\php7B9E.tmp" ["error"]=> int(0) ["size"]=> int(8266) } }
In addition to this the function accepts an $options array argument that can customize it’s behavior:
The $options parameter accepts an associative array to override the following global php.ini settings for parsing of the request body.
max_file_uploadsmax_input_varsmax_multipart_body_partspost_max_sizeupload_max_filesize
[$_POST, $_FILES] = request_parse_body([
'post_max_size' => '10M',
'upload_max_filesize' => '10M',
]);


