The Great Hateoas PHP Library
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.
With a Subscription, click any sentence in the script to jump to that part of the video!
Login SubscribeGoogle for "HATEOAS PHP" to find a fun library that a friend of mine made. This library has a bundle that integrates it into Symfony: so click to view the BazingaHateoasBundle and go straight to its docs. Before we talk about what it does: get it installed.
Installing BazingaHateoasBundle
Copy the composer require statement and then flip over to your terminal and paste that:
composer require willdurand/hateoas-bundle
This is a bundle, so grab the new bundle statement, open AppKernel
and pop that at the bottom:
// ... lines 1 - 5 | |
class AppKernel extends Kernel | |
{ | |
public function registerBundles() | |
{ | |
$bundles = array( | |
// ... lines 11 - 21 | |
new Bazinga\Bundle\HateoasBundle\BazingaHateoasBundle(), | |
); | |
// ... lines 24 - 33 | |
} | |
// ... lines 35 - 52 | |
} |
Perfect. Currently, we have our own super sweet annotation system for adding links. In Battle
, we use @Link
to create a programmer
link:
// ... lines 1 - 9 | |
/** | |
// ... lines 11 - 13 | |
* @Link( | |
* "programmer", | |
* route="api_programmers_show", | |
* params={"nickname": "object.getProgrammerNickname()"} | |
* ) | |
*/ | |
class Battle | |
// ... lines 21 - 138 |
Guess what! I completely stole that idea from this library. But now, to make our app a little simpler and to get some new features, let's replace our @Link
code with this library.
Adding the HATEOAS Annotation Links
Go back to the library itself, and scroll down to the first coding example. This uses an annotation system that looks pretty similar to ours. Copy the use
statement on top, open Battle
and paste that:
// ... lines 1 - 8 | |
use Hateoas\Configuration\Annotation as Hateoas; | |
// ... lines 10 - 141 |
Next, change the annotation to @Hateoas\Relation
:
// ... lines 1 - 10 | |
/** | |
// ... lines 12 - 14 | |
* @Hateoas\Relation( | |
// ... lines 16 - 20 | |
* ) | |
*/ | |
class Battle | |
// ... lines 24 - 141 |
Keep programmer
: that will still be the link's rel
. But add href=@Hateoas\Route
and pass that the name of the route: api_programmers_show
:
// ... lines 1 - 10 | |
/** | |
// ... lines 12 - 14 | |
* @Hateoas\Relation( | |
* "programmer", | |
* href=@Hateoas\Route( | |
* "api_programmers_show", | |
// ... line 19 | |
* ) | |
* ) | |
*/ | |
class Battle | |
// ... lines 24 - 141 |
Update params
to parameters
, and inside, set nickname
equal, and wrap the expression in expr()
:
// ... lines 1 - 10 | |
/** | |
// ... lines 12 - 14 | |
* @Hateoas\Relation( | |
* "programmer", | |
* href=@Hateoas\Route( | |
* "api_programmers_show", | |
* parameters={"nickname"= "expr(object.getProgrammerNickname())"} | |
* ) | |
* ) | |
*/ | |
class Battle | |
// ... lines 24 - 141 |
That translates our annotation format to the one used by the bundle. And the result is almost the same. Open BattleControllerTest
and copy the first method name:
// ... lines 1 - 6 | |
class BattleControllerTest extends ApiTestCase | |
{ | |
// ... lines 9 - 15 | |
public function testPOSTCreateBattle() | |
// ... lines 17 - 74 | |
} |
we have a test for a link near the bottom of this:
// ... lines 1 - 6 | |
class BattleControllerTest extends ApiTestCase | |
{ | |
// ... lines 9 - 15 | |
public function testPOSTCreateBattle() | |
{ | |
// ... lines 18 - 40 | |
$this->asserter()->assertResponsePropertyEquals( | |
$response, | |
'_links.programmer', | |
$this->adjustUri('/api/programmers/Fred') | |
); | |
// ... lines 46 - 48 | |
} | |
// ... lines 50 - 74 | |
} |
Change over to the terminal and, as long as Composer is done, run:
vendor/bin/phpunit --filter testPOSTCreateBattle
Check it out! It fails - but barely. This library still puts links under an _links
key, but instead of listing the URLs directly, it wraps each inside an object with an href
key. That's causes the failure.
Ok, fair enough. Let's fix that by updating the test to look for _links.programmer.href
:
// ... 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') | |
); | |
// ... lines 46 - 48 | |
} | |
// ... lines 50 - 74 | |
} |
Run the test again:
vendor/bin/phpunit --filter testPOSTCreateBattle
And now we're green.
Holy Toledo Batman: This is HAL JSON!
But guess what? It's no accident that this library used this exact format: with an _links
key and an href
below that. This is a semi-official standard format called HAL JSON.
Is there a similar bundle for Symfony 3?