Description
Description
Symfony's Request
class currently does not natively handle multipart/form-data
for non-POST (PUT/PATCH) requests. Developers are forced to rely on workarounds, such as method spoofing (_method=PUT
, see the $httpMethodParameterOverride
option in symfony/http-foundation/Request.php).
This limitation stems from PHP itself, which historically hasn't supported parsing multipart/form-data
for methods other than POST. However, as of PHP 8.4, the new request_parse_body()
function was introduced tackle this issue.
I found issue #9226, which was locked in 2023 and discussed this limitation. With the introduction of request_parse_body(), this could now be revisited.
References:
PHP Bug 55815
request_parse_body()
on PHP.Watch
Example
A small example what request_parse_body()
does. This is just a demo implementation in symfony/http-foundation/Request.php createFromGlobals()
to demonstrate the effect with PUT and PATCH requests:
public static function createFromGlobals(): static
{
$request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER);
if (str_starts_with($request->headers->get('CONTENT_TYPE', ''), 'application/x-www-form-urlencoded')
&& \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH'], true)
) {
parse_str($request->getContent(), $data);
$request->request = new InputBag($data);
}
+ if (str_starts_with($request->headers->get('CONTENT_TYPE', ''), 'multipart/form-data')
+ && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'PATCH'], true)
+ && function_exists('request_parse_body')
+ ) {
+ [$post, $files] = request_parse_body();
+ $request->request = new InputBag($post);
+ $request->files = new FileBag($files);
+ }
return $request;
}