On the client side I was using Backbone.js to manage all of the entities and generate the required JSON objects to send to the Silex based backend. This meant that the Controller would receive a string representation of the object it had to process. The parsing of this string was trivial of course but it was repeated code across all of the Controllers (actually just the POST/PUT/PATCH Controllers, but that was still a large part of the code base). It also meant that if I wanted to change how I handled input, it would need to be done in many classes.
I wanted to have a single place, outside of the Controller code (not a utility method) that parsed the input and exposed it in a way that the Controller could understand.
This was the kind of input JSON data that was sent (just an example with formatting applied)...
JSON
{
"gameId":"1513416078",
"category":"1",
"type":"0",
"cartType":"3"
}
To process something like that I added a before Middleware that intercepted and converted the input, for the appropriate methods. It looked something like this:
PHP
/* decode JSON data for API requests */
$app->before(function (Request $request) {
$method = $request->getMethod();
/* POST, PUT, PATCH */
if (in_array($method,
[Request::METHOD_POST, Request::METHOD_PUT, Request::METHOD_PATCH]))
{
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
$data = json_decode($request->getContent(), true);
$request->request->replace(is_array($data) ? $data : array());
}
}
});
What the above code did was it first checked whether the submit method was one of POST, PUT or PATCH. It then checked that the content type header was set to 'application/json'. Once both of those conditions were satisfied, the request body content was parsed as a JSON object and converted into an associative array.
Finally, the request parameter list was set to the associative array via the Symfony Request object replace() function. If the string could not be parsed as valid JSON input, an empty array was used instead.
Now it was possible to access each of the JSON object properties as if it was sent in as a standard POST parameter. For example, I could retrieve the 'gameId' property value like so...
PHP
function upsert(Request $request, Application $app, $id = null) {
$r = $request->request;
$r->get('gameId');
...
}
None of the Controllers had to deal with any JSON string to object conversion any longer!
I've since expanded the before Middleware to do a similar treatment for GET query parameters and added other handy features that I needed like request path validation, etc.
-i