If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeThe Battle representation includes the username of the programmer that fought. If you want more information about Fred, you can make a request to /api/programmers/Fred
:
... lines 1 - 6 | |
class BattleControllerTest extends ApiTestCase | |
{ | |
... lines 9 - 15 | |
public function testPOSTCreateBattle() | |
{ | |
... lines 18 - 37 | |
$this->asserter() | |
->assertResponsePropertyEquals($response, 'programmer', 'Fred'); | |
... lines 40 - 42 | |
} | |
... lines 44 - 68 | |
} |
That's something we'll document.
But! Wouldn't it be even more convenient if we added a link to that URL inside of the Battle representation? Then, instead of needing to go look up and hardcode the URL, the client could simply read and follow the link.
Whenever a link like this would be helpful, add it! First, look for it in the test: $this->asserter()->assertResponsePropertyEquals()
. For consistency, we decided to put links under an _links
key. So, look for _links.programmer
. This should equal $this->adjustUri('/api/programmers/Fred)
:
... lines 1 - 37 | |
$this->asserter() | |
->assertResponsePropertyEquals($response, 'programmer', 'Fred'); | |
$this->asserter()->assertResponsePropertyEquals( | |
$response, | |
'_links.programmer', | |
$this->adjustUri('/api/programmers/Fred') | |
); | |
... lines 46 - 76 |
All this method does is help account for the extra app_test.php
that's in the URL when testing:
... lines 1 - 21 | |
class ApiTestCase extends KernelTestCase | |
{ | |
... lines 24 - 358 | |
/** | |
* Call this when you want to compare URLs in a test | |
* | |
* (since the returned URL's will have /app_test.php in front) | |
* | |
* @param string $uri | |
* @return string | |
*/ | |
protected function adjustUri($uri) | |
{ | |
return '/app_test.php'.$uri; | |
} | |
} |
Perfect! Now, let's go add that link. First, open up the Programmer
entity. We added the self
link earlier via a cool annotation system we created:
... lines 1 - 9 | |
/** | |
... lines 11 - 15 | |
* @Link( | |
* "self", | |
* route = "api_programmers_show", | |
* params = { "nickname": "object.getNickname()" } | |
* ) | |
*/ | |
class Programmer | |
... lines 23 - 198 |
In Battle
, add something similar: @Link
- let that auto-complete for the use
statement. Set the name - or rel
- of the link to programmer
. This is the significance of the link: it could be anything, as long as you consistently use programmer
when linking to a programmer:
... lines 1 - 9 | |
/** | |
... lines 11 - 13 | |
* @Link( | |
* "programmer", | |
... lines 16 - 17 | |
* ) | |
*/ | |
class Battle | |
... lines 21 - 138 |
For the route, use api_programmers_show
: the route name to a single programmer:
... lines 1 - 9 | |
/** | |
... lines 11 - 13 | |
* @Link( | |
* "programmer", | |
* route="api_programmers_show", | |
... line 17 | |
* ) | |
*/ | |
class Battle | |
... lines 21 - 138 |
Finally, add params
: the wildcard parameters that need to be passed to the route. This route has a nickname
wildcard. Set it to an expression: object.getProgrammerNickname()
:
... lines 1 - 9 | |
/** | |
... lines 11 - 13 | |
* @Link( | |
* "programmer", | |
* route="api_programmers_show", | |
* params={"nickname": "object.getProgrammerNickname()"} | |
* ) | |
*/ | |
class Battle | |
... lines 21 - 138 |
That's the method we created down below earlier:
... lines 1 - 19 | |
class Battle | |
{ | |
... lines 22 - 119 | |
/** | |
* @Serializer\VirtualProperty() | |
* @Serializer\SerializedName("programmer") | |
*/ | |
public function getProgrammerNickname() | |
{ | |
return $this->programmer->getNickname(); | |
} | |
... lines 128 - 136 | |
} |
And that's all we need. Copy the method name again - testPostCreateBattle()
- and run the test:
./vendor/bin/phpunit --filter testPostCreateBattle
And it works.
Now, let me show you an awesome library that makes adding links even easier. In fact, I stole the @Link
annotation idea from it.
"Houston: no signs of life"
Start the conversation!
// composer.json
{
"require": {
"php": ">=5.5.9",
"symfony/symfony": "3.0.*", // v3.0.3
"doctrine/orm": "^2.5", // v2.5.4
"doctrine/doctrine-bundle": "^1.6", // 1.6.2
"doctrine/doctrine-cache-bundle": "^1.2", // 1.3.0
"symfony/swiftmailer-bundle": "^2.3", // v2.3.11
"symfony/monolog-bundle": "^2.8", // v2.10.0
"sensio/distribution-bundle": "^5.0", // v5.0.4
"sensio/framework-extra-bundle": "^3.0.2", // v3.0.14
"incenteev/composer-parameter-handler": "~2.0", // v2.1.2
"jms/serializer-bundle": "^1.1.0", // 1.1.0
"white-october/pagerfanta-bundle": "^1.0", // v1.0.5
"lexik/jwt-authentication-bundle": "^1.4", // v1.4.3
"willdurand/hateoas-bundle": "^1.1" // 1.1.1
},
"require-dev": {
"sensio/generator-bundle": "^3.0", // v3.0.6
"symfony/phpunit-bridge": "^3.0", // v3.0.3
"behat/behat": "~3.1@dev", // dev-master
"behat/mink-extension": "~2.2.0", // v2.2
"behat/mink-goutte-driver": "~1.2.0", // v1.2.1
"behat/mink-selenium2-driver": "~1.3.0", // v1.3.1
"phpunit/phpunit": "~4.6.0", // 4.6.10
"doctrine/doctrine-fixtures-bundle": "^2.3" // 2.3.0
}
}