smmehdisharifi/laravel-msgpack
A Laravel integration for MessagePack, the compact binary serialization format. Encode and decode MessagePack data in PHP/Laravel apps for smaller payloads and efficient data exchange, with framework-friendly helpers and configuration.
Start by reading the README's onboarding section (rewritten in v2.2.0) — it now walks through install → first response → negotiation in order, so you can skip the source on a first pass. Install with composer require smmehdisharifi/laravel-msgpack; there are no new runtime dependencies and nothing to publish to get a working response.
The first use case to try is a single API endpoint. Return a MessagePack response from a controller using the response macro:
return response()->msgpack(['status' => 'ok', 'user' => $user]);
Then verify the bytes are actually MessagePack, not JSON — curl -H 'Accept: application/x-msgpack' https://app.test/api/user | xxd | head should show bin-format markers rather than a leading {. This single check catches most misconfiguration before you touch resources.
If your API is resource-driven, your second step is the new v2.2.0 path: return an Eloquent API resource directly and let the package serialize it.
return UserResource::make($user)->response()->msgpack();
Where to look first when something is off: the service provider registration (to confirm the macros and negotiation middleware are wired), then config/msgpack.php if you published it. Don't start by reading the serialization internals — negotiation and macro resolution are the usual culprits.
Resource-first APIs (new in v2.2.0). The headline change is first-class support for Laravel JSON resources and resource collections, so you can keep your normal JsonResource / ResourceCollection classes and only swap the response call. This is the pattern to prefer for new code: your transformation logic stays portable between JSON and MessagePack clients.
// Single resource
return PostResource::make($post)->response()->msgpack();
// Collection
return PostResource::collection($posts)->response()->msgpack();
Paginated resources. Offset and cursor paginators now preserve data, links, and meta through MessagePack. This means you can serve one paginated resource to both JSON and MessagePack consumers without hand-building the envelope:
return PostResource::collection(Post::paginate(25))->response()->msgpack();
return PostResource::collection(Post::cursorPaginate(25))->response()->msgpack();
Consumers decode data and read pagination state from links/meta exactly as they would from JSON — only the wire format differs. Keep pagination in the resource layer rather than wrapping responses manually, or you'll lose the preservation guarantees.
Status codes and headers. response()->msgpack() now carries through the status and custom headers set on the resource response. The idiomatic pattern is to configure those on the resource response and let the macro serialize:
return PostResource::make($post)
->response()
->setStatusCode(201)
->header('X-Request-Id', $requestId)
->msgpack();
Explicit macro arguments remain authoritative — if you pass status or headers into msgpack() directly, those win over the resource's values. Pick one style per codebase; mixing them within a controller makes status behaviour hard to reason about during debugging.
Content negotiation as a cross-cutting concern. Rather than branching per controller, let the negotiation middleware select the format from Accept, and expose a small helper/formatter used by both your resource classes and any raw array responses. Teams typically add a Blade-less API test that hits the same route with Accept: application/json and Accept: application/x-msgpack and asserts both decode to the same payload — cheap regression coverage for anything negotiation touches.
Incremental adoption. Because nothing breaks, roll MessagePack out behind negotiation on a single high-traffic endpoint (analytics, dashboards, large collections) and compare payload sizes against the JSON path using the benchmark article the release links. MessagePack pays off most where payloads are large and consumers control their own decoding; it pays off least where clients are browsers you don't control.
dd()/dump() behind the JSON path.Accept: application/json (or */*) will not get MessagePack. If you expected MessagePack and got JSON, check the Accept header before you debug the serializer — this is the single most common false alarm.msgpack() override them. If a status code "disappears," look for an explicit argument in the same call chain.data/links/meta preservation is specific to returning paginated resources through the macro. Wrapping a paginator in response()->msgpack($paginator->toArray()) bypasses that path and can produce a different shape from your JSON endpoint.msgpack_unpack($response->getContent())) rather than string comparison, and remember Laravel's assertJson helpers don't apply. A shared test helper that decodes whichever format the request negotiated keeps suites format-agnostic.composer.json and run the suite after upgrading — the CI matrix covers all of these, but your app's Laravel patch level and any custom resource classes aren't part of those 52 tests.How can I help you explore Laravel packages today?