Buy Access to Course
13.

Embedding Objects with Hal?

Share this awesome video!

|

Keep on Learning!

Check out the Hal example on their docs. There are actually three different sections of the json: the actual data - like currentlyProcessing, _links and _embedded.

Here's a cool idea: we know that it's nice to add links to a response. These are called relations: they point to related resources. But there's another way to add a relation to a response: embed the related resource right in the JSON.

Remember: the whole point of adding link relations is to make life easier for your API clients. If embedding the data is even easier than advertising a link, do it.

In fact, let's pretend that when we return a Battle resource, we still want to include a link to the related Programmer, but we also want to embed that Programmer entirely.

Adding an Embedded Relation

To do that, after href, add an embedded="expr()" with object.getProgrammer():

142 lines | src/AppBundle/Entity/Battle.php
// ... lines 1 - 10
/**
// ... lines 12 - 14
* @Hateoas\Relation(
* "programmer",
* href=@Hateoas\Route(
* "api_programmers_show",
* parameters={"nickname"= "expr(object.getProgrammerNickname())"}
* ),
* embedded = "expr(object.getProgrammer())"
* )
*/
class Battle
// ... lines 25 - 142

Let's see what this looks like! Open BattleControllerTest and right at the bottom, add our handy $this->debugResponse($response):

// ... lines 1 - 6
class BattleControllerTest extends ApiTestCase
{
// ... lines 9 - 15
public function testPOSTCreateBattle()
{
// ... lines 18 - 40
$this->asserter()->assertResponsePropertyEquals(
$response,
'_links.programmer.href',
$this->adjustUri('/api/programmers/Fred')
);
$this->debugResponse($response);
// ... lines 47 - 49
}
// ... lines 51 - 75
}

Perfect! Copy that method name and run it:

./vendor/bin/phpunit --filter testPOSTCreateBattle

Oh, cool: we still have the relation in _links, but now we also have an entire programmer resource in _embedded. So when you setup these @Hateoas\Relation annotations:

142 lines | src/AppBundle/Entity/Battle.php
// ... lines 1 - 10
/**
// ... lines 12 - 14
* @Hateoas\Relation(
* "programmer",
* href=@Hateoas\Route(
* "api_programmers_show",
* parameters={"nickname"= "expr(object.getProgrammerNickname())"}
* ),
* embedded = "expr(object.getProgrammer())"
* )
*/
class Battle
// ... lines 25 - 142

You can choose whether you want this to be a link or an embedded object.

And OK, we cheated on this test by looking at it first, but now I guess we should specifically have a test for it. Add: $this->asserter()->assertResponsePropertyEquals() with $response. Look for _embedded.programmer.nickname to be equal to our friend Fred:

// ... lines 1 - 6
class BattleControllerTest extends ApiTestCase
{
// ... lines 9 - 15
public function testPOSTCreateBattle()
{
// ... lines 18 - 40
$this->asserter()->assertResponsePropertyEquals(
$response,
'_links.programmer.href',
$this->adjustUri('/api/programmers/Fred')
);
$this->asserter()->assertResponsePropertyEquals(
$response,
'_embedded.programmer.nickname',
'Fred'
);
// ... lines 51 - 53
}
// ... lines 55 - 79
}

Run that!

./vendor/bin/phpunit --filter testPOSTCreateBattle

It passes! Now let's customize how these links render.