oldcodefork / laminas-api-tools-hal
Laminas Module providing Hypermedia Application Language assets and rendering
Requires
- php: ^7.3 || ~8.0.0 || ~8.1.0 || ~8.2.0
- ext-json: *
- laminas-api-tools/api-tools-api-problem: ^1.2.1
- laminas/laminas-eventmanager: ^3.0.1
- laminas/laminas-filter: ^2.7.1
- laminas/laminas-http: ^2.5.4
- laminas/laminas-hydrator: ^3.2.0 || ^4.0.1
- laminas/laminas-mvc: ^3.0.2
- laminas/laminas-paginator: ^2.7
- laminas/laminas-stdlib: ^3.0.1
- laminas/laminas-uri: ^2.5.2
- laminas/laminas-view: ^2.11.4
- laminas/laminas-zendframework-bridge: ^1.0
- psr/link: ^1.0 || ^2.0
Requires (Dev)
- laminas/laminas-coding-standard: ~2.3.0
- laminas/laminas-modulemanager: ^2.10.1
- phpdocumentor/reflection-docblock: ^5.2.2
- phpspec/prophecy-phpunit: ^2.0
- phpunit/phpunit: ^9.3
- psalm/plugin-phpunit: ^0.15.1
- vimeo/psalm: ^4.6
Replaces
- zfcampus/zf-hal: ^1.6.0
README
π·πΊ Π ΡΡΡΠΊΠΈΠΌ Π³ΡΠ°ΠΆΠ΄Π°Π½Π°ΠΌ
ΠΡ, ΡΡΠ°ΡΡΠ½ΠΈΠΊΠΈ Laminas, ΡΠΎΠ΄ΠΈΠ»ΠΈΡΡ ΠΈ ΠΆΠΈΠ²Π΅ΠΌ Π² ΡΠ°Π·Π½ΡΡ ΡΡΡΠ°Π½Π°Ρ . Π£ ΠΌΠ½ΠΎΠ³ΠΈΡ ΠΈΠ· Π½Π°Ρ Π΅ΡΡΡ Π΄ΡΡΠ·ΡΡ, ΡΠΎΠ΄ΡΡΠ²Π΅Π½Π½ΠΈΠΊΠΈ ΠΈ ΠΊΠΎΠ»Π»Π΅Π³ΠΈ ΠΊΠ°ΠΊ Π² Π ΠΎΡΡΠΈΠΈ, ΡΠ°ΠΊ ΠΈ Π² Π£ΠΊΡΠ°ΠΈΠ½Π΅. ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΈΠ· Π½Π°Ρ ΡΠΎΠ΄ΠΈΠ»ΠΈΡΡ Π² Π ΠΎΡΡΠΈΠΈ. ΠΠ΅ΠΊΠΎΡΠΎΡΡΠ΅ ΠΈΠ· Π½Π°Ρ ΠΆΠΈΠ²ΡΡ Π² Π ΠΎΡΡΠΈΠΈ. Π£ Π½Π΅ΠΊΠΎΡΠΎΡΡΡ Π±Π°Π±ΡΡΠΊΠΈ ΠΈ Π΄Π΅Π΄ΡΡΠΊΠΈ ΡΡΠ°ΠΆΠ°Π»ΠΈΡΡ Ρ ΡΠ°ΡΠΈΡΡΠ°ΠΌΠΈ Π²ΠΎ ΠΡΠΎΡΠΎΠΉ ΠΌΠΈΡΠΎΠ²ΠΎΠΉ Π²ΠΎΠΉΠ½Π΅. ΠΠ΄Π΅ΡΡ Π½ΠΈΠΊΡΠΎ Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅Ρ ΡΠ°ΡΠΈΠ·ΠΌ.
Π£ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΈΠ· Π½Π°Ρ Π΅ΡΡΡ ΡΠΊΡΠ°ΠΈΠ½ΡΠΊΠ°Ρ ΡΠΎΠ΄ΡΡΠ²Π΅Π½Π½ΠΈΡΠ°, ΠΊΠΎΡΠΎΡΠ°Ρ ΡΠΏΠ°ΡΠ»Π°ΡΡ ΠΈΠ· Π΄ΠΎΠΌΠ° Π²ΠΌΠ΅ΡΡΠ΅ Ρ ΡΡΠ½ΠΎΠΌ. ΠΠΎΠ΅Π·Π΄ Π·Π°Π΄Π΅ΡΠΆΠ°Π»ΡΡ ΠΈΠ·-Π·Π° Π±ΠΎΠΌΠ±Π΅ΠΆΠΊΠΈ Π½Π° Π΄ΠΎΡΠΎΠ³Π΅ Π²ΠΏΠ΅ΡΠ΅Π΄ΠΈ. Π£ Π½Π°Ρ Π΅ΡΡΡ Π΄ΡΡΠ·ΡΡ, ΠΊΠΎΡΠΎΡΡΠ΅ ΠΏΡΡΡΡΡΡΡ Π² Π±ΠΎΠΌΠ±ΠΎΡΠ±Π΅ΠΆΠΈΡΠ°Ρ . ΠΡ Ρ ΡΡΠ΅Π²ΠΎΠ³ΠΎΠΉ ΠΆΠ΄Π΅ΠΌ Π²Π΅ΡΡΠΎΡΠΊΠΈ ΠΎΡ Π½ΠΈΡ ΠΏΠΎΡΠ»Π΅ Π²ΠΎΠ·Π΄ΡΡΠ½ΡΡ Π½Π°Π»Π΅ΡΠΎΠ², ΠΊΠΎΡΠΎΡΡΠ΅ Π±Π΅ΡΠΏΠΎΡΡΠ΄ΠΎΡΠ½ΠΎ Π½Π°Π½ΠΎΡΡΡ ΡΠ΄Π°ΡΡ ΠΈ ΠΏΠΎΠΏΠ°Π΄Π°ΡΡ ΠΏΠΎ Π±ΠΎΠ»ΡΠ½ΠΈΡΠ°ΠΌ, ΡΠΊΠΎΠ»Π°ΠΌ, Π΄Π΅ΡΡΠΊΠΈΠΌ ΡΠ°Π΄Π°ΠΌ ΠΈ Π΄ΠΎΠΌΠ°ΠΌ. ΠΡ Π½Π΅ Π±Π΅ΡΠ΅ΠΌ ΡΡΠΎ ΠΈΠ· ΠΊΠ°ΠΊΠΈΡ -Π»ΠΈΠ±ΠΎ Π‘ΠΠ. ΠΡ Π½Π°Π±Π»ΡΠ΄Π°Π΅ΠΌ ΡΡΠΎ Π½Π°ΠΏΡΡΠΌΡΡ.
ΠΡ Π΄ΠΎΠ²Π΅ΡΡΠ΅ΡΠ΅ Π½Π°ΠΌ Π΄ΠΎΡΡΠ°ΡΠΎΡΠ½ΠΎ, ΡΡΠΎΠ± ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π½Π°ΡΠΈ ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΡ, ΠΈ ΠΌΡ ΠΏΡΠΎΡΠΈΠΌ Π²Π°Ρ Π΄ΠΎΠ²Π΅ΡΠΈΡΡΡΡ Π½Π°ΠΌ Π²Π½ΠΎΠ²Ρ. ΠΡ Π½ΡΠΆΠ΄Π°Π΅ΠΌΡΡ Π² ΠΏΠΎΠΌΠΎΡΠΈ. ΠΡΡ ΠΎΠ΄ΠΈΡΠ΅ ΠΈ ΠΏΡΠΎΡΠ΅ΡΡΡΠΉΡΠ΅ ΠΏΡΠΎΡΠΈΠ² ΡΡΠΎΠΉ Π±Π΅ΡΠΏΠΎΠ»Π΅Π·Π½ΠΎΠΉ Π²ΠΎΠΉΠ½Ρ. ΠΡΡΠ°Π½ΠΎΠ²ΠΈΡΠ΅ ΠΊΡΠΎΠ²ΠΎΠΏΡΠΎΠ»ΠΈΡΠΈΠ΅. Π‘ΠΊΠ°ΠΆΠΈΡΠ΅ "ΠΠ΅Ρ Π²ΠΎΠΉΠ½Π΅!"
πΊπΈ 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
This module provides the ability to generate Hypermedia Application Language JSON representations.
Requirements
Please see the composer.json file.
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
If you use laminas-component-installer, that plugin will install api-tools-hal as a module for you.
Configuration
User Configuration
This module utilizes the top level key api-tools-hal
for user configuration.
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 theHal
plugin when no hydrator is configured for an entity class.render_embedded_entities
- boolean, defaulttrue
, to render full embedded entities in HAL responses; iffalse
, embedded entities will contain only their relational links.render_embedded_collections
- boolean, default istrue
, to render collections in HAL responses; iffalse
, only a collection's relational links will be rendered.hydrators
- a map of entity class names to hydrator service names that theHal
plugin can use when hydrating entities.
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 generateself
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 theentity_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 totrue
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, onlyself
links will be rendered. default value isnull
, 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 totrue
(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
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 totrue
when you are using a proxy (for usingHTTP_X_FORWARDED_PROTO
,HTTP_X_FORWARDED_HOST
, andHTTP_X_FORWARDED_PORT
instead ofSSL_HTTPS
,HTTP_HOST, SERVER_PORT
)
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
Events
Laminas\ApiTools\Hal\Plugin\Hal 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 theLaminas\ApiTools\Hal\Collection
being rendered.renderCollection.post
defines two parameters:collection
, which is theLaminas\ApiTools\Hal\Collection
being rendered, andpayload
, anArrayObject
representation of the collection, including the page count, size, and total items, and links.renderEntity
defines one parameter,entity
, which is theLaminas\ApiTools\Hal\Entity
being rendered.renderEntity.post
defines two parameters:entity
, which is theLaminas\ApiTools\Hal\Entity
being rendered, andpayload
, anArrayObject
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
, theLaminas\ApiTools\Hal\Collection
to which the entity belongs.entity
, the current entity being rendered; this may or may not be aLaminas\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 aLaminas\ApiTools\Hal\Link\Link
instance. This is generally useful fromLaminas\ApiTools\Rest\RestController::create()
, when you may want to manipulate the self relational link for purposes of generating theLink
header.
Listeners
Laminas\ApiTools\Hal\Module::onRender
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
Models
Laminas\ApiTools\Hal\Collection
Collection
is responsible for modeling general collections as HAL collections, and composing
relational links.
Laminas\ApiTools\Hal\Entity
Entity
is responsible for modeling general purpose entities and plain objects as HAL entities, and
composing relational links.
Laminas\ApiTools\Hal\Link\Link
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
LinkCollection
is a model responsible for aggregating a collection of Link
instances.
Laminas\ApiTools\Hal\Metadata\Metadata
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
The MetadataMap
aggregates an array of class name keyed Metadata
instances to be used in
producing HAL entities, links, or collections.
Extractors
Laminas\ApiTools\Hal\Extractor\LinkExtractor
LinkExtractor
is responsible for extracting a link representation from Link
instance.
Laminas\ApiTools\Hal\Extractor\LinkCollectionExtractor
LinkCollectionExtractor
is responsible for extracting a collection of Link
instances. It also
composes a LinkExtractor
for extracting individual links.
Controller Plugins
Laminas\ApiTools\Hal\Plugin\Hal (a.k.a. "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
Laminas\ApiTools\Hal\View\HalJsonModel
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
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
HalJsonStrategy
is responsible for selecting HalJsonRenderer
when it identifies a HalJsonModel
as the controller service response.