PHPackages                             rnd-cosoft/api-tools-hal - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. rnd-cosoft/api-tools-hal

ActiveLibrary[HTTP &amp; Networking](/categories/http)

rnd-cosoft/api-tools-hal
========================

Laminas Module providing Hypermedia Application Language assets and rendering

1.11.1(2y ago)01.4k14BSD-3-ClausePHPPHP ~8.1.0 || ~8.2.0 || ~8.3.0

Since Dec 31Pushed 2y agoCompare

[ Source](https://github.com/rnd-cosoft/api-tools-hal)[ Packagist](https://packagist.org/packages/rnd-cosoft/api-tools-hal)[ Docs](https://api-tools.getlaminas.org)[ RSS](/packages/rnd-cosoft-api-tools-hal/feed)WikiDiscussions 1.11.x Synced 1mo ago

READMEChangelog (2)Dependencies (20)Versions (37)Used By (4)

Laminas HAL
===========

[](#laminas-hal)

[![Build Status](https://github.com/laminas-api-tools/api-tools-hal/workflows/Continuous%20Integration/badge.svg)](https://github.com/laminas-api-tools/api-tools-hal/actions?query=workflow%3A%22Continuous+Integration%22)

> ## 🇷🇺 Русским гражданам
>
> [](#-русским-гражданам)
>
> Мы, участники Laminas, родились и живем в разных странах. У многих из нас есть друзья, родственники и коллеги как в России, так и в Украине. Некоторые из нас родились в России. Некоторые из нас живут в России. У некоторых бабушки и дедушки сражались с фашистами во Второй мировой войне. Здесь никто не поддерживает фашизм.
>
> У одного из нас есть украинская родственница, которая спаслась из дома вместе с сыном. Поезд задержался из-за бомбежки на дороге впереди. У нас есть друзья, которые прячутся в бомбоубежищах. Мы с тревогой ждем весточки от них после воздушных налетов, которые беспорядочно наносят удары и попадают по больницам, школам, детским садам и домам. Мы не берем это из каких-либо СМИ. Мы наблюдаем это напрямую.
>
> Вы доверяете нам достаточно, чтоб использовать наши программы, и мы просим вас довериться нам вновь. Мы нуждаемся в помощи. Выходите и протестуйте против этой бесполезной войны. Остановите кровопролитие. Скажите "Нет войне!"
>
> ## 🇺🇸 To Citizens of Russia
>
> [](#-to-citizens-of-russia)
>
> We at Laminas come from all over the world. Many of us have friends, family and colleagues in both Russia and Ukraine. Some of us were born in Russia. Some of us currently live in Russia. Some have grandparents who fought Nazis in World War II. Nobody here supports fascism.
>
> One team member has a Ukrainian relative who fled her home with her son. The train was delayed due to bombing on the road ahead. We have friends who are hiding in bomb shelters. We anxiously follow up on them after the air raids, which indiscriminately fire at hospitals, schools, kindergartens and houses. We're not taking this from any media. These are our actual experiences.
>
> You trust us enough to use our software. We ask that you trust us to say the truth on this. We need your help. Go out and protest this unnecessary war. Stop the bloodshed. Say "stop the war!"

Introduction
------------

[](#introduction)

This module provides the ability to generate [Hypermedia Application Language](http://tools.ietf.org/html/draft-kelly-json-hal-06) JSON representations.

Requirements
------------

[](#requirements)

Please see the [composer.json](composer.json) file.

Installation
------------

[](#installation)

Run the following `composer` command:

```
$ composer require laminas-api-tools/api-tools-hal
```

Alternately, manually add the following to your `composer.json`, in the `require` section:

```
"require": {
    "laminas-api-tools/api-tools-hal": "^1.4"
}
```

And then run `composer update` to ensure the module is installed.

Finally, add the module name to your project's `config/application.config.php` under the `modules`key:

```
return [
    /* ... */
    'modules' => [
        /* ... */
        'Laminas\ApiTools\Hal',
    ],
    /* ... */
];
```

> ### laminas-component-installer
>
> [](#laminas-component-installer)
>
> If you use [laminas-component-installer](https://github.com/laminas/laminas-component-installer), that plugin will install api-tools-hal as a module for you.

Configuration
=============

[](#configuration)

### User Configuration

[](#user-configuration)

This module utilizes the top level key `api-tools-hal` for user configuration.

#### Key: `renderer`

[](#key-renderer)

This is a configuration array used to configure the `api-tools-hal` `Hal` view helper/controller plugin. It consists of the following keys:

- `default_hydrator` - when present, this named hydrator service will be used as the default hydrator by the `Hal` plugin when no hydrator is configured for an entity class.
- `render_embedded_entities` - boolean, default `true`, to render full embedded entities in HAL responses; if `false`, embedded entities will contain only their relational links.
- `render_embedded_collections` - boolean, default is `true`, to render collections in HAL responses; if `false`, only a collection's relational links will be rendered.
- `hydrators` - a map of entity class names to hydrator service names that the `Hal` plugin can use when hydrating entities.

#### Key: `metadata_map`

[](#key-metadata_map)

The metadata map is used to hint to the `Hal` plugin how it should render objects of specific class types. When the `Hal` plugin encounters an object found in the metadata map, it will use the configuration for that class when creating a representation; this information typically indicates how to generate relational links, how to serialize the object, and whether or not it represents a collection.

Each class in the metadata map may contain one or more of the following configuration keys:

- `entity_identifier_name` - name of the class property (after serialization) used for the identifier.
- `route_name` - a reference to the route name used to generate `self` relational links for the collection or entity.
- `route_identifier_name` - the identifier name used in the route that will represent the entity identifier in the URI path. This is often different than the `entity_identifier_name` as each variable segment in a route must have a unique name.
- `hydrator` - the hydrator service name to use when serializing an entity.
- `is_collection` - boolean; set to `true` when the class represents a collection.
- `links` - an array of configuration for constructing relational links; see below for the structure of links.
- `entity_route_name` - route name for embedded entities of a collection.
- `route_params` - an array of route parameters to use for link generation.
- `route_options` - an array of options to pass to the router during link generation.
- `url` - specific URL to use with this resource, if not using a route.
- `max_depth` - integer; limit to what nesting level entities and collections are rendered; if the limit is reached, only `self` links will be rendered. default value is `null`, which means no limit: if unlimited circular references are detected, an exception will be thrown to avoid infinite loops.
- `force_self_link` - boolean; set whether a self-referencing link should be automatically generated for the entity. Defaults to `true` (since its recommended).

The `links` property is an array of arrays, each with the following structure:

```
[
    'rel'   => 'link relation',
    'url'   => 'string absolute URI to use', // OR
    'route' => [
        'name'    => 'route name for this link',
        'params'  => [ /* any route params to use for link generation */ .,
        'options' => [ /* any options to pass to the router */ .,
    .,
.,
// repeat as needed for any additional relational links
```

#### Key: `options`

[](#key-options)

The options key is used to configure general options of the Hal plugin. For now we have only one option available who contains the following configuration key:

- `use_proxy` - boolean; set to `true` when you are using a proxy (for using `HTTP_X_FORWARDED_PROTO`, `HTTP_X_FORWARDED_HOST`, and `HTTP_X_FORWARDED_PORT` instead of `SSL_HTTPS`, `HTTP_HOST, SERVER_PORT`)

### System Configuration

[](#system-configuration)

The following configuration is present to ensure the proper functioning of this module in a Laminas-based application.

```
// Creates a "HalJson" selector for use with laminas-api-tools/api-tools-content-negotiation
'api-tools-content-negotiation' => [
    'selectors' => [
        'HalJson' => [
            'Laminas\ApiTools\Hal\View\HalJsonModel' => [
                'application/json',
                'application/*+json',
            ],
        ],
    ],
],
```

Laminas Events
==============

[](#laminas-events)

### Events

[](#events)

#### Laminas\\ApiTools\\Hal\\Plugin\\Hal Event Manager

[](#laminasapitoolshalpluginhal-event-manager)

The `Laminas\ApiTools\Hal\Plugin\Hal` triggers several events during its lifecycle. From the `EventManager`instance composed into the HAL plugin, you may attach to the following events:

- `renderCollection`
- `renderCollection.post`
- `renderEntity`
- `renderEntity.post`
- `createLink`
- `renderCollection.entity`
- `getIdFromEntity`

As an example, you could listen to the `renderEntity` event as follows (the following is done within a `Module` class for a Laminas module and/or Laminas API Tools API module):

```
class Module
{
    public function onBootstrap($e)
    {
        $app = $e->getTarget();
        $services = $app->getServiceManager();
        $helpers  = $services->get('ViewHelperManager');
        $hal      = $helpers->get('Hal');

        // The HAL plugin's EventManager instance does not compose a SharedEventManager,
        // so you must attach directly to it.
        $hal->getEventManager()->attach('renderEntity', [$this, 'onRenderEntity']);
    }

    public function onRenderEntity($e)
    {
        $entity = $e->getParam('entity');
        if (! $entity->getEntity() instanceof SomeTypeIHaveDefined) {
            // do nothing
            return;
        }

        // Add a "describedBy" relational link
        $entity->getLinks()->add(\Laminas\ApiTools\Hal\Link\Link::factory([
            'rel' => 'describedBy',
            'route' => [
                'name' => 'my/api/docs',
            ],
        ]));
    }
}
```

Notes on individual events:

- `renderCollection` defines one parameter, `collection`, which is the `Laminas\ApiTools\Hal\Collection` being rendered.
- `renderCollection.post` defines two parameters: `collection`, which is the `Laminas\ApiTools\Hal\Collection` being rendered, and `payload`, an `ArrayObject`representation of the collection, including the page count, size, and total items, and links.
- `renderEntity` defines one parameter, `entity`, which is the `Laminas\ApiTools\Hal\Entity` being rendered.
- `renderEntity.post` defines two parameters: `entity`, which is the `Laminas\ApiTools\Hal\Entity` being rendered, and `payload`, an `ArrayObject`representation of the entity, including links.
- `createLink` defines the following event parameters:
    - `route`, the route name to use when generating the link, if any.
    - `id`, the entity identifier value to use when generating the link, if any.
    - `entity`, the entity for which the link is being generated, if any.
    - `params`, any additional routing parameters to use when generating the link.
- `renderCollection.entity` defines the following event parameters:
    - `collection`, the `Laminas\ApiTools\Hal\Collection` to which the entity belongs.
    - `entity`, the current entity being rendered; this may or may not be a `Laminas\ApiTools\Hal\Entity`.
    - `route`, the route name for the current entity.
    - `routeParams`, route parameters to use when generating links for the current entity.
    - `routeOptions`, route options to use when generating links for the current entity.
- `getIdFromEntity` defines one parameter, `entity`, which is an array or object from which an identifier needs to be extracted.
- `fromLink.pre` (since 1.5.0) defines one parameter, `linkDefinition`, which is a `Laminas\ApiTools\Hal\Link\Link` instance. This is generally useful from `Laminas\ApiTools\Rest\RestController::create()`, when you may want to manipulate the self relational link for purposes of generating the `Link` header.

### Listeners

[](#listeners)

#### Laminas\\ApiTools\\Hal\\Module::onRender

[](#laminasapitoolshalmoduleonrender)

This listener is attached to `MvcEvent::EVENT_RENDER` at priority `100`. If the controller service result is a `HalJsonModel`, this listener attaches the `Laminas\ApiTools\Hal\JsonStrategy` to the view at priority `200`.

Laminas Services
================

[](#laminas-services)

### Models

[](#models)

#### Laminas\\ApiTools\\Hal\\Collection

[](#laminasapitoolshalcollection)

`Collection` is responsible for modeling general collections as HAL collections, and composing relational links.

#### Laminas\\ApiTools\\Hal\\Entity

[](#laminasapitoolshalentity)

`Entity` is responsible for modeling general purpose entities and plain objects as HAL entities, and composing relational links.

#### Laminas\\ApiTools\\Hal\\Link\\Link

[](#laminasapitoolshallinklink)

`Link` is responsible for modeling a relational link. The `Link` class also has a static `factory()` method that can take an array of information as an argument to produce valid `Link`instances.

#### Laminas\\ApiTools\\Hal\\Link\\LinkCollection

[](#laminasapitoolshallinklinkcollection)

`LinkCollection` is a model responsible for aggregating a collection of `Link` instances.

#### Laminas\\ApiTools\\Hal\\Metadata\\Metadata

[](#laminasapitoolshalmetadatametadata)

`Metadata` is responsible for collecting all the necessary dependencies, hydrators and other information necessary to create HAL entities, links, or collections.

#### Laminas\\ApiTools\\Hal\\Metadata\\MetadataMap

[](#laminasapitoolshalmetadatametadatamap)

The `MetadataMap` aggregates an array of class name keyed `Metadata` instances to be used in producing HAL entities, links, or collections.

### Extractors

[](#extractors)

#### Laminas\\ApiTools\\Hal\\Extractor\\LinkExtractor

[](#laminasapitoolshalextractorlinkextractor)

`LinkExtractor` is responsible for extracting a link representation from `Link` instance.

#### Laminas\\ApiTools\\Hal\\Extractor\\LinkCollectionExtractor

[](#laminasapitoolshalextractorlinkcollectionextractor)

`LinkCollectionExtractor` is responsible for extracting a collection of `Link` instances. It also composes a `LinkExtractor` for extracting individual links.

### Controller Plugins

[](#controller-plugins)

#### Laminas\\ApiTools\\Hal\\Plugin\\Hal (a.k.a. "Hal")

[](#laminasapitoolshalpluginhal-aka-hal)

This class operates both as a view helper and as a controller plugin. It is responsible for providing controllers the facilities to generate HAL data models, as well as rendering relational links and HAL data structures.

### View Layer

[](#view-layer)

#### Laminas\\ApiTools\\Hal\\View\\HalJsonModel

[](#laminasapitoolshalviewhaljsonmodel)

`HalJsonModel` is a view model that when used as the result of a controller service response signifies to the `api-tools-hal` module that the data within the model should be utilized to produce a JSON HAL representation.

#### Laminas\\ApiTools\\Hal\\View\\HalJsonRenderer

[](#laminasapitoolshalviewhaljsonrenderer)

`HalJsonRenderer` is a view renderer responsible for rendering `HalJsonModel` instances. In turn, this renderer will call upon the `Hal` plugin/view helper in order to transform the model content (an `Entity` or `Collection`) into a HAL representation.

#### Laminas\\ApiTools\\Hal\\View\\HalJsonStrategy

[](#laminasapitoolshalviewhaljsonstrategy)

`HalJsonStrategy` is responsible for selecting `HalJsonRenderer` when it identifies a `HalJsonModel`as the controller service response.

###  Health Score

40

—

FairBetter than 88% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity18

Limited adoption so far

Community26

Small or concentrated contributor base

Maturity84

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 81.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~44 days

Recently: every ~76 days

Total

37

Last Release

737d ago

Major Versions

0.9.1 → 1.0.02019-12-31

PHP version history (9 changes)0.6.0PHP &gt;=5.3.3

0.8.0PHP &gt;=5.4.8

0.9.0PHP &gt;=5.3.23

1.2.0PHP &gt;=5.5

1.4.0PHP ^5.6 || ^7.0

1.7.x-devPHP ^7.3 || ~8.0.0

1.8.0PHP ^7.3 || ~8.0.0 || ~8.1.0

1.10.x-devPHP ~8.0.0 || ~8.1.0 || ~8.2.0

1.11.0PHP ~8.1.0 || ~8.2.0 || ~8.3.0

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1388877?v=4)[Kristijonas Lučinskas](/maintainers/kristijonas)[@Kristijonas](https://github.com/Kristijonas)

---

Top Contributors

[![weierophinney](https://avatars.githubusercontent.com/u/25943?v=4)](https://github.com/weierophinney "weierophinney (929 commits)")[![neeckeloo](https://avatars.githubusercontent.com/u/1768645?v=4)](https://github.com/neeckeloo "neeckeloo (33 commits)")[![michalbundyra](https://avatars.githubusercontent.com/u/7423207?v=4)](https://github.com/michalbundyra "michalbundyra (29 commits)")[![Wilt](https://avatars.githubusercontent.com/u/2419627?v=4)](https://github.com/Wilt "Wilt (20 commits)")[![TomHAnderson](https://avatars.githubusercontent.com/u/493920?v=4)](https://github.com/TomHAnderson "TomHAnderson (15 commits)")[![acabala](https://avatars.githubusercontent.com/u/530622?v=4)](https://github.com/acabala "acabala (11 commits)")[![javabudd](https://avatars.githubusercontent.com/u/611826?v=4)](https://github.com/javabudd "javabudd (9 commits)")[![gsomoza](https://avatars.githubusercontent.com/u/106219?v=4)](https://github.com/gsomoza "gsomoza (8 commits)")[![localheinz](https://avatars.githubusercontent.com/u/605483?v=4)](https://github.com/localheinz "localheinz (8 commits)")[![rogervila](https://avatars.githubusercontent.com/u/6053012?v=4)](https://github.com/rogervila "rogervila (7 commits)")[![telkins](https://avatars.githubusercontent.com/u/53731?v=4)](https://github.com/telkins "telkins (6 commits)")[![tjlytle](https://avatars.githubusercontent.com/u/125074?v=4)](https://github.com/tjlytle "tjlytle (6 commits)")[![ralphschindler](https://avatars.githubusercontent.com/u/76674?v=4)](https://github.com/ralphschindler "ralphschindler (6 commits)")[![ezimuel](https://avatars.githubusercontent.com/u/475967?v=4)](https://github.com/ezimuel "ezimuel (6 commits)")[![snapshotpl](https://avatars.githubusercontent.com/u/312655?v=4)](https://github.com/snapshotpl "snapshotpl (6 commits)")[![MichaelGooden](https://avatars.githubusercontent.com/u/1275012?v=4)](https://github.com/MichaelGooden "MichaelGooden (5 commits)")[![bartbrinkman](https://avatars.githubusercontent.com/u/8309358?v=4)](https://github.com/bartbrinkman "bartbrinkman (5 commits)")[![geerteltink](https://avatars.githubusercontent.com/u/9497586?v=4)](https://github.com/geerteltink "geerteltink (5 commits)")[![rnd-cosoft](https://avatars.githubusercontent.com/u/57006314?v=4)](https://github.com/rnd-cosoft "rnd-cosoft (3 commits)")[![oxodesign](https://avatars.githubusercontent.com/u/175456?v=4)](https://github.com/oxodesign "oxodesign (3 commits)")

---

Tags

laminasrestpsr-13halmoduleapi-tools

###  Code Quality

TestsPHPUnit

Static AnalysisPsalm

Type Coverage Yes

### Embed Badge

![Health badge](/badges/rnd-cosoft-api-tools-hal/health.svg)

```
[![Health](https://phpackages.com/badges/rnd-cosoft-api-tools-hal/health.svg)](https://phpackages.com/packages/rnd-cosoft-api-tools-hal)
```

###  Alternatives

[mezzio/mezzio-hal

Hypertext Application Language implementation for PHP and PSR-7

20456.9k6](/packages/mezzio-mezzio-hal)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
