Reference
Reference
This section covers all configuration formats supported by Hateoas: XML, YAML, and PHP annotations. Each format allows you to define relations, links, embedded resources, and exclusion strategies for your API representations.
XML
You can configure Hateoas using XML files. The full XML configuration supports relations, routes with parameters, embedded resources, exclusion strategies, and relation providers.
<?xml version="1.0" encoding="UTF-8"?>
<serializer>
<class name="Acme\Demo\Representation\User"
h:providers="Class::getRelations, getRelations"
xmlns:h="https://github.com/willdurand/Hateoas">
<h:relation rel="self">
<h:href uri="http://acme.com/foo/1" />
</h:relation>
<h:relation rel="expr(object.getFriendsDynamicRel())">
<h:href route="user_friends" generator="my_custom_generator">
<h:parameter name="id" value="expr(object.getId())" />
<h:parameter name="page" value="1" />
</h:href>
<h:embedded xml-element-name="users">
<h:content>expr(object.getFriends())</h:content>
<h:exclusion ... />
</h:embedded>
<h:exclusion
groups="Default, user_full"
since-version="1.0"
until-version="2.2"
exclude-if="expr(object.getFriends() === null)" />
</h:relation>
</class>
</serializer>
The full XML schema definition is available at hateoas.xsd.
YAML
YAML configuration provides a concise way to define relations, routes, embedded resources, and exclusion strategies.
Acme\Demo\Representation\User:
relations:
-
rel: self
href: http://acme.com/foo/1
-
rel: expr(object.getFriendsDynamicRel())
href:
route: user_friends
parameters:
id: expr(object.getId())
page: 1
generator: my_custom_generator
absolute: false
embedded:
content: expr(object.getFriends())
xmlElementName: users
exclusion: ...
exclusion:
groups: [Default, user_full]
since_version: 1.0
until_version: 2.2
exclude_if: expr(object.getFriends() === null)
relation_providers: [ 'Class::getRelations', 'getRelations' ]
Annotations
Hateoas provides a rich set of PHP annotations that you can use directly on your classes to define relations, routes, embedded resources, and exclusion rules.
@Relation
The @Relation annotation
can be defined on a class. It describes a relation with a name, a link (href),
and optionally an embedded resource.
use Hateoas\Configuration\Annotation as Hateoas;
/**
* @Hateoas\Relation(
* name = "self",
* href = "http://hello",
* embedded = "expr(object.getHello())",
* attributes = { "foo" = "bar" },
* exclusion = ...,
* )
*/
| Property | Required | Content | Expression Language |
|---|---|---|---|
name |
Yes | string | Yes |
href |
If no embedded |
string / @Route | Yes |
embedded |
If no href |
string / @Embedded | Yes |
attributes |
No | array | Yes (values) |
exclusion |
No | @Exclusion | N/A |
@Route
The @Route annotation is used
within the href property of @Relation to define a route-based
link with parameters.
use Hateoas\Configuration\Annotation as Hateoas;
/**
* @Hateoas\Relation(
* "self",
* href = @Hateoas\Route(
* "user_get",
* parameters = { "id" = "expr(object.getId())" }
* )
* )
*/
| Property | Required | Content | Expression Language |
|---|---|---|---|
name |
Yes | string | Yes |
parameters |
Defaults to array() |
array | Yes (values) |
absolute |
Defaults to false |
boolean | Yes |
generator |
No | string / null | No |
@Embedded
The @Embedded annotation is
used within the embedded property of @Relation to define
an embedded resource.
use Hateoas\Configuration\Annotation as Hateoas;
/**
* @Hateoas\Relation(
* "friends",
* embedded = @Hateoas\Embedded(
* "expr(object.getFriends())",
* exclusion = @Hateoas\Exclusion(groups = {"Default", "friend_list"}),
* xmlElementName = "users"
* )
* )
*/
| Property | Required | Content | Expression Language |
|---|---|---|---|
content |
Yes | string / object | Yes |
serializer |
No | @Exclusion | N/A |
xmlElementName |
Defaults to array() |
string | Yes |
@Exclusion
The @Exclusion annotation
is used in the exclusion property of @Relation and
@Embedded. It controls when a relation should be excluded from the
serialized output.
| Property | Required | Content | Expression Language |
|---|---|---|---|
groups |
No | array | No |
sinceVersion |
No | float / integer | No |
untilVersion |
No | float / integer | No |
maxDepth |
No | integer | No |
excludeIf |
No | string / boolean | Yes |
The excludeIf property is particularly useful for conditionally excluding
a relation. It accepts an expression that evaluates to a boolean. If the expression
returns true, the relation is excluded from the serialized output. This
is helpful when a related object may be null:
/**
* @Hateoas\Relation(
* "manager",
* href = @Hateoas\Route(
* "user_get",
* parameters = { "id" = "expr(object.getManager().getId())" }
* ),
* exclusion = @Hateoas\Exclusion(
* excludeIf = "expr(null === object.getManager())"
* )
* )
*/
class User
{
public function getId() {}
/** @return User|null */
public function getManager() {}
}
Without excludeIf, the expression
object.getManager().getId() would throw an error when the manager
is null. The excludeIf property ensures the relation is
only rendered when a valid manager exists.
@RelationProvider
The @RelationProvider annotation can be defined on a class. It is useful
when you need to add multiple relations or links that are determined at runtime. Instead
of defining each relation statically, you point to a method that returns an array of
Relation objects.
use Hateoas\Configuration\Annotation as Hateoas;
/**
* @Hateoas\RelationProvider("getRelations")
*/
class User
{
public static function getRelations()
{
return array(
new Relation(
'self',
new Route('user_get', array('id' => 1))
),
);
}
}
You can also reference a method on a different class using the
Class::method syntax:
/**
* @Hateoas\RelationProvider("Acme\Demo\RelationProvider\UserRelationProvider::getRelations")
*/
class User
{
// ...
}
If you need a fully custom relation provider, you can implement the
RelationProviderInterface:
use Hateoas\Configuration\Relation;
use Hateoas\Configuration\Route;
use Hateoas\Configuration\Provider\RelationProviderInterface;
class UserRelationProvider implements RelationProviderInterface
{
/**
* @return Relation[]
*/
public function getRelations($object, $class)
{
return array(
new Relation(
'self',
new Route(
'user_get',
array('id' => $object->getId())
)
),
new Relation(
'friends',
new Route(
'user_friends',
array('id' => $object->getId())
)
),
);
}
}