HAL - Hypertext Application Language is a JSON dialect which gives a consistent and easy way to add HATEOAS - Hypertext As The Engine Of Application State - to your API. This library makes composing HAL responses easy including embedded data.
This library consists of a Hydrator Manager and you will write hydrators for the classes you want to serve as HAL. Central to this library is a Resource object on which HAL resources are attached.
Although this library is for Laravel, it is not specific to Eloquent. This same library can be used with any datasource to compose a HAL response.
This is a direct implementation of https://tools.ietf.org/html/draft-kelly-json-hal-08
return $this->hydratorManager->resource($data)
->addLink('self', route('routeName::fetch', $class->id))
->addEmbeddedResource('example', $class->example)
->toArray();
- Create a hydrator manager
- Create a hydrator for the User class
- Create a hydrator for the Role class
- Compose these into a HAL resource and return HAL from a controller action
namespace App\HAL;
use ApiSkeletons\Laravel\HAL\HydratorManager as HALHydratorManager;
final class HydratorManager extends HALHydratorManager
{
public function __construct()
{
$this->classHydrators = [
\App\Models\Role::class => \App\HAL\Hydrator\RoleHydrator::class,
\App\Models\User::class => \App\HAL\Hydrator\UserHydrator::class,
];
}
namespace App\HAL\Hydrator;
use ApiSkeletons\Laravel\HAL\Hydrator;
use ApiSkeletons\Laravel\HAL\Resource;
use App\Models\User;
final class UserHydrator extends Hydrator
{
public function extract($class): Resource
{
$data = [];
$fields = [
'id',
'name',
'email',
];
// Extract fields into an array to be used by the resource
foreach ($fields as $field) {
$data[$field] = $class->$field;
}
// Create a new resource and assign self link and extract the
// roles into an embedded resource. Note `addEmbeddedResources`
// is used for arrays and `addEmbeddedResource` is used for classes
return $this->hydratorManager->resource($data)
->addLink('self', route('hal/user::fetch', $class->id))
->addEmbeddedResources('roles', $class->roles)
;
}
}
namespace App\HAL\Hydrator;
use ApiSkeletons\Laravel\HAL\Hydrator;
use ApiSkeletons\Laravel\HAL\Resource;
use App\Models\Role;
final class RoleHydrator extends Hydrator
{
public function extract($class): Resource
{
$data = [];
$fields = [
'id',
'name',
'guard_name',
];
// Extract fields into an array to be used by the resource
foreach ($fields as $field) {
$data[$field] = $class->$field;
}
// Create a new resource and assign self link and extract the
// roles into an embedded resource. Note `addEmbeddedResources`
// is used for arrays and `addEmbeddedResource` is used for classes
return $this->hydratorManager->resource($data)
->addLink('self', route('hal/role::fetch', $class->id))
;
}
}
public function fetch(User $user, Request $request)
{
$hydratorManager = new \App\HAL\HydratorManager();
return $hydratorManager->extract($user)->toArray();
}
{
"_links":{
"self":{
"href":"https://apiskeletons.com/user/1"
}
},
"id":1,
"name":"Tom H Anderson",
"email":"tom.h.anderson@gmail.com",
"_embedded":{
"roles":[
{
"_links":{
"self":{
"href":"https://apiskeletons.com/role/1"
}
},
"id":1,
"name":"admin",
"guard_name":"web",
}
]
}
}