Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Hateoas Bundle Laravel Package

talentrydev/hateoas-bundle

A Symfony bundle for building HATEOAS-compliant APIs, adding hypermedia links and relations to your resources so clients can discover and navigate endpoints dynamically. Integrates with your existing serialization to expose self-descriptive, discoverable responses.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: this is not a Laravel package. talentrydev/hateoas-bundle is a Symfony bundle — specifically a republished/forked copy of willdurand/BazingaHateoasBundle, which wires the willdurand/hateoas library into the Symfony full-stack framework (service container, serializer, bundle registration in AppKernel/bundles.php). There is no ServiceProvider, no config/*.php publish target, and no Laravel-facing API. As a Laravel developer you should treat this repository as a reference implementation, not a dependency.

Given that, the useful "getting started" path is:

  1. Skip the bundle, install the library. composer require willdurand/hateoas is what actually does the work. The bundle only contributes Symfony DI glue you will rewrite anyway.
  2. Look at the bundle's DependencyInjection/Configuration.php and Resources/config/*.xml to understand how the upstream library is meant to be configured (metadata cache, serializer, expression language for link hrefs). That is the only thing this repo teaches you that the library docs don't.
  3. First use case: take a domain object or Eloquent model that needs _links and _embedded, annotate it (or configure it), and serialize it to HAL JSON instead of hand-writing link arrays in every controller.

A realistic Laravel smoke test:

// composer require willdurand/hateoas
$hateoas = \Hateoas\HateoasBuilder::create()->build();

$hateoas->serialize($order, 'json'); // produces _links / _embedded

If that works, you have 90% of what the bundle offered, without a Symfony kernel.

Implementation Patterns

Direct library usage inside a Laravel service provider. Bind a singleton built by HateoasBuilder and inject it into a base controller or a response macro. This is the closest analogue to what the bundle does with bazinga_hateoas.serializer.

// AppServiceProvider::register()
$this->app->singleton(\Hateoas\Hateoas::class, function () {
    return \Hateoas\HateoasBuilder::create()
        ->setExpressionEvaluator(new \Symfony\Component\ExpressionLanguage\ExpressionLanguage())
        ->build();
});

// Response macro
Response::macro('hateoas', function ($object) {
    return response()->json(
        json_decode(app(\Hateoas\Hateoas::class)->serialize($object, 'json'), true)
    );
});

Annotate models, keep controllers thin. The library's model is annotation/attribute-driven (@Hateoas\Relation, @Hateoas\Embedded). Use it on DTOs or Eloquent models so link construction lives with the resource, not in ten controllers. Prefer dedicated resource/DTO classes over Eloquent models — the metadata cache keys on class + file mtime and churns badly on frequently edited models.

Compose with API Resources rather than replacing them. A common pattern: build the payload with JsonResource, then post-process to inject _links. HATEOAS relations are about behavior (what can I do next), not field shaping — let Resources own the shape and Hateoas own the links.

Mirror the bundle's config surface in a config file. The bundle exposes roughly bazinga_hateoas.metadata.cache (e.g. a file cache under %kernel.cache_dir%) and serializer settings. Reproduce that as config/hateoas.php with metadata.cache.path => storage_path('framework/hateoas') plus a cache: true toggle per environment — you want it off in local and on in production.

Use relation providers for cross-cutting links. If every resource needs self and collection links derived from route names, write one relation provider and apply it globally instead of repeating annotations. This also keeps route-name changes in one place.

Gotchas and Tips

  • The Symfony/serializer dependency is the real trap. willdurand/hateoas leans on symfony/serializer and symfony/expression-language. Those install fine in a Laravel app, but you inherit a second serializer stack alongside Laravel's, with different normalization semantics. Budget time for the boundary; don't try to unify them.
  • The package is effectively dead. Last release 2021-03-18, zero stars, zero dependents. It is a fork of an abandoned bundle tracking an abandoned-ish integration. Pin nothing to it long-term; if you vendor anything, vendor the patterns, not the package.
  • PHP 8 attributes are the sticking point. The 2021 era of this stack is annotation-centric (doctrine/annotations + docblock parsing). Modern PHP will work for the library core, but annotation reading is fragile and slow; attributes support varies by version. Verify against the library's current docs, not this bundle's README, which predates the shift.
  • bazinga_hateoas namespace and config root will mislead you in copy-paste. Anything you find in this repo's docs assumes AppKernel::registerBundles(), services.xml, and %kernel.cache_dir%. Translating that to config/app.php + AppServiceProvider is manual, and most tutorials you'll find online are for the Symfony bundle, not the library.
  • Metadata cache invalidation is the #1 debugging annoyance. When links mysteriously don't update, it's the metadata cache keyed on file mtime — clear it before you debug your logic. In a Docker setup with bind mounts, mtime can look stale.
  • Expression-language hrefs fail silently-ish. A typo in an href expression like expr("/orders/" ~ object.getId()) throws deep inside the evaluator with an unhelpful message. Wrap serialization in a test that asserts the exact _links structure; don't eyeball it.
  • Extension points worth knowing: custom RelationProviders, a custom UrlGenerator (this is where you'd plug Laravel\UrlGenerator/route() in place of Symfony's router — the bundle's bazinga_hateoas.url_generator service is the exact seam), and the expression evaluator. The URL generator swap is mandatory in Laravel, not optional.
  • Consider the alternatives first. spatie/laravel-fractal (with its serializer layer) or plain JsonResource + a small links() helper covers most real HATEOAS needs with none of this dependency baggage. Reach for willdurand/hateoas only if you specifically want its annotation model and relation-provider machinery.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib