php - Phalcon 5 - Sending post request to controller results in empty post data
I'm using a docker setup with php 8.0.15 + phalcon 5.0.0beta2 and i'm trying to do a simple post request using the fetch api to a route.
/* inside router.php */
$apiGroup = new Router\Group();
$apiGroup->setPrefix('/api');
$apiGroup->addPost('/user', 'UserApi::post');
/* somewhere in my controller action */
$data = [
'email' => $this->request->getPost('email', [ Filter::FILTER_EMAIL ]),
'password' => $this->request->getPost('password', [ Filter::FILTER_STRING ]),
];
/* in my js */
fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(someData)
}).then(dostuff);
My problem is that $this->request->getPost('email')
returns null and when debugging I saw that $_POST is also empty. Using $this->request->getRawBody()
and $this->request->getJsonRawBody()
do yield results since my data is actually there. I could very well just use getJsonRawBody()
, but i'm wondering why the behaviour? (I used phalcon 3.* for another project and it worked just fine)
Thanks.
Answer
Solution:
The documentation for Phalcon's Request object explains that it is primarily a wrapper around PHP's native "superglobals", such as $_POST
. In particular:
The $_POST superglobal contains an associative array that contains the variables passed to the current script via the HTTP POST method when using
application/x-www-form-urlencoded
ormultipart/form-data
as the HTTPContent-Type
in the request. You can retrieve the data stored in the array by calling thegetPost()
method
Note that important caveat that this array is only populated when using two specific content types - specifically, the two content types that browsers use when submitting HTML forms. Form processing is the original task PHP was built for, and it can handle things like file uploads; but it doesn't natively do anything with JSON, XML, or other input types.
(As an aside, that documentation is subtly wrong: despite its name, $_POST
will be populated for any HTTP method with an appropriate request body, e.g. PUT
, just as $_GET
is populated even when the method is POST
.)
In your request, you're not using those content types, because you're posting a JSON string, so PHP doesn't populate $_POST
, and Phalcon doesn't have anything to read with getPost()
.
As you've discovered, there's a separate method which allows you to decode the JSON body to a PHP array:
getJsonRawBody(): Gets decoded JSON HTTP raw request body
There's no mention of JSON at all in the Phalcon 3.4 Request documentation so I'm not sure whether that functionality has changed, you've misremembered, or you were using some additional plugin or configuration.
The REST tutorial shows usage of getJsonRawBody()
in both the 5.0 version and the 3.4 version.