Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Creating the Invalid JSON ApiProblem, and then...

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $10.00

The nice API Problem JSON format always has a type key, so let's at least start looking for that in the response. Use $this->asserter()->assertResponsePropertyEquals() and pass it the $response and type as the key. For the value - how about invalid_body_format. That's our second special error "type" - the first was validation_error.

... lines 1 - 5
class ProgrammerControllerTest extends ApiTestCase
{
... lines 8 - 147
public function testInvalidJson()
{
... lines 150 - 162
$this->assertEquals(400, $response->getStatusCode());
$this->asserter()->assertResponsePropertyEquals($response, 'type', 'invalid_body_format');
}
... line 166
}

This should get our test to fail again:

./bin/phpunit -c app --filter testInvalidJson

Gooood - we're still returning the exception HTML.

Creating the ApiProblem

Let's fix this just like we did for validation errors: by creating an ApiProblem object. First, we need a new type constant. Create a second constant called TYPE_INVALID_REQUEST_BODY_FORMAT and set that to the string from our test: invalid_body_format. Setup a title for this too: how about "Invalid JSON format sent". And I better fix my syntax error:

... lines 1 - 7
class ApiProblem
{
const TYPE_VALIDATION_ERROR = 'validation_error';
const TYPE_INVALID_REQUEST_BODY_FORMAT = 'invalid_body_format';
private static $titles = array(
self::TYPE_VALIDATION_ERROR => 'There was a validation error',
self::TYPE_INVALID_REQUEST_BODY_FORMAT => 'Invalid JSON format sent',
);
... lines 17 - 58
}

Back in ProgrammerController, we can get to work: $apiProblem = new ApiProblem(). Pass it the 400 status code and the type: ApiProblem::TYPE_INVALID_REQUEST_BODY_FORMAT:

... lines 1 - 17
class ProgrammerController extends BaseController
{
... lines 20 - 141
private function processForm(Request $request, FormInterface $form)
{
$data = json_decode($request->getContent(), true);
if ($data === null) {
$apiProblem = new ApiProblem(400, ApiProblem::TYPE_INVALID_REQUEST_BODY_FORMAT);
... lines 147 - 148
}
... lines 150 - 152
}
... lines 154 - 187
}

We're stuck

Gosh, everything is going really well! And now we're stuck. For validation, we took the ApiProblem, turned it into a Response and returned it. But inside processForm(), we're big trouble: the return value of this method isn't being used. We can only throw an exception to stop the flow. And while we can control the status code of an exception, the response body that an HttpException generates is still an HTML error page.

Leave a comment!

0
Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial uses an older version of Symfony. The concepts of REST and errors are still valid, but I recommend using API Platform in new Symfony apps.

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": ">=5.3.3",
        "symfony/symfony": "2.6.*", // v2.6.11
        "doctrine/orm": "~2.2,>=2.2.3,<2.5", // v2.4.7
        "doctrine/dbal": "<2.5", // v2.4.4
        "doctrine/doctrine-bundle": "~1.2", // v1.4.0
        "twig/extensions": "~1.0", // v1.2.0
        "symfony/assetic-bundle": "~2.3", // v2.6.1
        "symfony/swiftmailer-bundle": "~2.3", // v2.3.8
        "symfony/monolog-bundle": "~2.4", // v2.7.1
        "sensio/distribution-bundle": "~3.0,>=3.0.12", // v3.0.21
        "sensio/framework-extra-bundle": "~3.0,>=3.0.2", // v3.0.7
        "incenteev/composer-parameter-handler": "~2.0", // v2.1.0
        "hautelook/alice-bundle": "0.2.*", // 0.2
        "jms/serializer-bundle": "0.13.*" // 0.13.0
    },
    "require-dev": {
        "sensio/generator-bundle": "~2.3", // v2.5.3
        "behat/behat": "~3.0", // v3.0.15
        "behat/mink-extension": "~2.0.1", // v2.0.1
        "behat/mink-goutte-driver": "~1.1.0", // v1.1.0
        "behat/mink-selenium2-driver": "~1.2.0", // v1.2.0
        "phpunit/phpunit": "~4.6.0" // 4.6.4
    }
}
userVoice