fsc/hateoas-bundle
Symfony bundle that adds HATEOAS hypermedia links to your API responses. Define relations and links with annotations, integrate with JMS Serializer and Symfony routing, and expose discoverable HAL/JSON-LD resources so clients can navigate your API at runtime.
Architecture fit — the headline issue: despite being catalogued as a Laravel/PHP package, fsc/hateoas-bundle is a Symfony bundle, and everything of value in it is glued to Symfony-specific contracts: a Bundle subclass, a DependencyInjection extension with a configuration tree, compiler passes, RouterInterface for link generation, and RequestStack for the current request. None of those integration surfaces exist in Laravel. Its serialization behaviour is delivered as a JMSSerializerBundle event subscriber, so even the output layer assumes a serializer Laravel does not ship. As a drop-in dependency, fit is low; as a design reference for declarative hypermedia, fit is moderate to good.
What is actually reusable: the conceptual model — declarative relation and embedding metadata on resources, a Link value object, router-driven URL generation, and HAL-style _links emission. That is a small surface (a handful of classes, on the order of a few hundred to ~1k LOC), which is precisely why the port is tractable and why the 4.9 opportunity score is credible: PHP has no first-class declarative HATEOAS story in the Laravel ecosystem, and this package demonstrates the shape of one.
Integration feasibility: a Laravel port is feasible but is a build, not an install. It requires a ServiceProvider with publishable config, replacing annotations with PHP 8 attributes, replacing RouterInterface with Illuminate\Routing\UrlGenerator, and reimplementing the serializer handler against either Eloquent API Resources or a Fractal-based layer. Content-negotiation, which Symfony's format listener handles for free, needs a middleware in Laravel.
Technical risk: high and concentrated in abandonment. This is Symfony 2.x/3.x-era code from roughly 2013–2016, likely pinned to jms/serializer 0.x/1.x and PHP ≤7.x constraints, with zero dependents — meaning no downstream consumers exercising it, no bug reports, no community patches, and no security response. No CVE process exists for it. Treat any code lifted from it as code we now own.
Key questions for the requester:
links block on responses? The answer changes buy-vs-build entirely.Stack fit: do not add this to composer.json. In a Laravel stack, the idiomatic equivalents are league/fractal (with spatie/laravel-fractal for the Laravel glue) plus a custom HAL serializer, or JSON:API via laravel-json-api. If the organisation is Symfony-first, API Platform supersedes this package entirely and is actively maintained — that recommendation should be made explicitly rather than defaulting to the bundle.
Migration path (ranked):
Link concepts into an internal Laravel package, rebuild the serializer handler on native resources, add attribute-based metadata and a negotiation middleware. We own it, we test it, no abandoned dependency.Compatibility to validate before committing: original composer.json PHP and Symfony constraints; JMS Serializer major version; whether the code uses annotations (requires doctrine/annotations) or attributes; PSR-7 vs. HttpFoundation assumptions; and the Accept-header handling the bundle inherited from Symfony's format listener. Each of these is a rewrite point, not a config change.
Sequencing:
_links/_embedded shape, error representation. This is the expensive-to-change decision and it must not be co-designed with implementation.Do not parallelise steps 1 and 2; the most common failure here is a contract that drifts to match whatever the serializer happened to emit.
Maintenance: assume total ownership from day one. There is no upstream to patch against, no release cadence, and no maintainer response. Budget ongoing ownership as an internal library with a named owner, versioning, and a test suite — not as a third-party dependency.
Support: no vendor, thin documentation (README-level), negligible community footprint. Knowledge will be concentrated in the one or two engineers who do the port. That is a bus-factor risk worth naming to stakeholders in the same breath as the delivery estimate.
Scaling: link generation itself is cheap, but embedded relations are the scaling hazard — each embedding is a potential N+1 and a payload multiplier. Hypermedia responses also need correct cache semantics: Vary: Accept, and stable absolute URLs, otherwise CDN and proxy caches will serve the wrong representation or stale links. Serialized representations become a cacheable artefact, which is an advantage only if the caching layer is designed for it up front.
Failure modes to design against:
Ramp-up: HATEOAS fluency is uncommon in the average Laravel team; most engineers have shipped REST with a links array and little more. Expect roughly a sprint for a mid-level engineer to become productive inside the ported code, plus review capacity from someone who genuinely knows HAL or JSON:API. Factor that review into the plan — it is the cheapest insurance against shipping a hypermedia API that no client actually follows.
How can I help you explore Laravel packages today?