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())
                )
            ),
        );
    }
}