Hateoas
A PHP library to support implementing representations for HATEOAS REST web services.
Install / Use
/learn @willdurand/HateoasREADME
Hateoas
A PHP library to support implementing representations for HATEOAS REST web services.
- Installation
- Usage
- Reference
- Internals
- Versioning
Installation
The recommended way to install Hateoas is through
Composer. Require the willdurand/hateoas package
by running the following command:
composer require willdurand/hateoas
This will resolve the latest stable version.
Otherwise, install the library and setup the autoloader yourself.
If you want to use annotations for configuration you need
to install the doctrine/annotations package:
composer require doctrine/annotations
If your app uses PHP 8.1 or higher it is recommended to use native PHP attributes. In this case you don't need to install the Doctrine package.
Working With Symfony
There is a bundle for that! Install the BazingaHateoasBundle, and enjoy!
Usage
Important:
For those who use the
1.0version, you can jump to this documentation page.For those who use the
2.0version, you can jump to this documentation page.The following documentation has been written for Hateoas 3.0 and above.
Introduction
Hateoas leverages the Serializer library to provide a nice way to build HATEOAS REST web services. HATEOAS stands for Hypermedia as the Engine of Application State, and adds hypermedia links to your representations (i.e. your API responses). HATEOAS is about the discoverability of actions on a resource.
For instance, let's say you have a User API which returns a representation of a single user as follow:
{
"user": {
"id": 123,
"first_name": "John",
"last_name": "Doe"
}
}
In order to tell your API consumers how to retrieve the data for this specific
user, you have to add your very first link to this representation, let's
call it self as it is the URI for this particular user:
{
"user": {
"id": 123,
"first_name": "John",
"last_name": "Doe",
"_links": {
"self": { "href": "http://example.com/api/users/123" }
}
}
}
Let's dig into Hateoas now.
Configuring Links
In Hateoas terminology, links are seen as relations added to resources. It is worth mentioning that relations also refer to embedded resources too, but this topic will be covered in the Embedding Resources section.
A link is a relation which is identified by a name (e.g. self) and that
has an href parameter:
use JMS\Serializer\Annotation as Serializer;
use Hateoas\Configuration\Annotation as Hateoas;
/**
* @Serializer\XmlRoot("user")
*
* @Hateoas\Relation("self", href = "expr('/api/users/' ~ object.getId())")
*/
class User
{
/** @Serializer\XmlAttribute */
private $id;
private $firstName;
private $lastName;
public function getId() {}
}
</details>
<details open>
<summary>Attribute (PHP 8.1 and greater)</summary>
use JMS\Serializer\Annotation as Serializer;
use Hateoas\Configuration\Annotation as Hateoas;
#[Serializer\XmlRoot('user')]
#[Hateoas\Relation('self', href: "expr('/api/users/' ~ object.getId())")]
class User
{
#[Serializer\XmlAttribute]
private $id;
private $firstName;
private $lastName;
public function getId() {}
}
</details>
In the example above, we configure a self relation that is a link because of
the href parameter. Its value, which may look weird at first glance, will be
extensively covered in The Expression Language
section. This special value is used to generate a URI.
In this section, annotations/attributes are used to configure Hateoas. XML and YAML formats are also supported. If you wish, you can use plain PHP too.
Important: you must configure both the Serializer and Hateoas the same way. E.g. if you use YAML for configuring Serializer, use YAML for configuring Hateoas.
The easiest way to try HATEOAS is with the HateoasBuilder. The builder has
numerous methods to configure the Hateoas serializer, but we won't dig into
them right now (see The HateoasBuilder).
Everything works fine out of the box:
use Hateoas\HateoasBuilder;
$hateoas = HateoasBuilder::create()->build();
$user = new User(42, 'Adrien', 'Brault');
$json = $hateoas->serialize($user, 'json');
$xml = $hateoas->serialize($user, 'xml');
The $hateoas object is an instance of JMS\Serializer\SerializerInterface,
coming from the Serializer library. Hateoas does not come with its own
serializer, it hooks into the JMS Serializer.
By default, Hateoas uses the Hypertext Application
Language (HAL) for JSON
serialization. This specifies the structure of the response (e.g. that
"links" should live under a _links key):
{
"id": 42,
"first_name": "Adrien",
"last_name": "Brault",
"_links": {
"self": {
"href": "/api/users/42"
}
}
}
For XML, Atom Links are used by default:
<user id="42">
<first_name><![CDATA[Adrien]]></first_name>
<last_name><![CDATA[Brault]]></last_name>
<link rel="self" href="/api/users/42"/>
</user>
It is worth mentioning that these formats are the default ones, not the only available ones. You can use different formats through different serializers, and even add your owns.
Now that you know how to add links, let's see how to add embedded resources.
Embedding Resources
Sometimes, it's more efficient to embed related resources rather than link to them, as it prevents clients from having to make extra requests to fetch those resources.
An embedded resource is a named relation that contains data, represented
by the embedded parameter.
use JMS\Serializer\Annotation as Serializer;
use Hateoas\Configuration\Annotation as Hateoas;
/**
* ...
*
* @Hateoas\Relation(
* "manager",
* href = "expr('/api/users/' ~ object.getManager().getId())",
* embedded = "expr(object.getManager())",
* exclusion = @Hateoas\Exclusion(excludeIf = "expr(object.getManager() === null)")
* )
*/
class User
{
...
/** @Serializer\Exclude */
private $manager;
}
</details>
<details open>
<summary>Attribute (PHP 8.1 and greater)</summary>
use JMS\Serializer\Annotation as Serializer;
use Hateoas\Configuration\Annotation as Hateoas;
#[Hateoas\Relation(
'manager',
href: "expr('/api/users/' ~ object.getManager().getId())",
embedded: "expr(object.getManager())",
exclusion: new Hateoas\Exclusion(excludeif: "expr(object.getManager() === null)"),
)]
class User
{
...
#[Serializer\Exclude]
private $manager;
}
</details>
Note: You will need to exclude the manager property from the serialization, otherwise both the serializer and Hateoas
Related Skills
bluebubbles
342.5kUse when you need to send or manage iMessages via BlueBubbles (recommended iMessage integration). Calls go through the generic message tool with channel="bluebubbles".
gh-issues
342.5kFetch GitHub issues, spawn sub-agents to implement fixes and open PRs, then monitor and address PR review comments. Usage: /gh-issues [owner/repo] [--label bug] [--limit 5] [--milestone v1.0] [--assignee @me] [--fork user/repo] [--watch] [--interval 5] [--reviews-only] [--cron] [--dry-run] [--model glm-5] [--notify-channel -1002381931352]
healthcheck
342.5kHost security hardening and risk-tolerance configuration for OpenClaw deployments
node-connect
342.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps

