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

Rest Api Bundle Laravel Package

kununu/rest-api-bundle

kununu/rest-api-bundle is a Symfony bundle for PHP that packages reusable infrastructure and conventions for building REST APIs, helping teams standardize endpoints, request handling, and responses across services.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this before composer require: it is not a Laravel package, and it is not really a public package.

kununu/rest-api-bundle is a Symfony bundle. It has no service provider, no Laravel auto-discovery entry, and no integration with Laravel's container, router, request lifecycle, or validation. It sits on top of mediamonks/rest-api-bundle, which itself hooks into Symfony's HttpKernel (event subscribers, ParamConverter, DI compiler passes, annotation/attribute reading). In a Laravel app, composer require will pull a pile of symfony/* components and change nothing about how your app behaves. The zero stars / zero dependents confirms what the description implies: this is kununu's internal bundle published to Packagist so their own services can install it, not a package with an outside user base.

So the honest "getting started" is two paths:

If you are evaluating this for a Laravel service: stop. Use the Laravel-native equivalents table in the next section. Nothing here is worth the impedance mismatch.

If you are inheriting or auditing a Symfony service that already depends on it:

  1. Check composer.json first — the symfony/* constraints, the pinned mediamonks/rest-api-bundle version, and the PHP floor. That tells you whether it is even installable on a current stack.
  2. Install both (the kununu bundle will pull the parent transitively): composer require kununu/rest-api-bundle.
  3. Register both bundles in config/bundles.php (or AppKernel), parent first.
  4. Where to look first is not this repo. Roughly 90% of the behavior comes from vendor/mediamonks/rest-api-bundle/README.md. Read that end to end. Then diff vendor/kununu/rest-api-bundle/src against it — the kununu delta is thin and largely undocumented, so the diff is the documentation.
  5. First use case to exercise: a controller that accepts a typed JSON body and returns a view model — e.g. POST /api/things deserializing into a DTO, validating it, and returning 201 with a serialized representation. If that round-trips, the wiring is correct.

Implementation Patterns

The bundle's value is a request-DTO → domain → view-model → serialized-response pipeline, with serializer groups, pagination, problem+json errors, and HTTP caching handled by convention rather than per-controller code.

1. The canonical controller. Deserialize the body into a DTO (via the bundle's request-body param converter / annotation), hand it to your domain service, return a view model through the response builder:

/**
 * @RequestBody(class="App\Dto\CreateThing")
 */
public function create(RequestBody $body, ResponseBuilder $builder, Request $request): Response
{
    $thing = $this->service->create($body);

    return $builder->build(new ThingView($thing), $request);
}

The view model implements the bundle's ViewModelInterface; the builder turns it into a Response and hands it to symfony/serializer with the right groups.

2. Serializer groups as API versions. Annotate view-model properties with groups (api:v1, api:detail), and let the request select a group set — typically a ?view= query parameter. This is the bundle's answer to versioning and to "don't leak internals."

3. Pagination as a contract, not a habit. Accept the bundle's pagination object off the request, return a paginated response wrapping the collection plus metadata. Consumers get stable page/limit/total/_links shapes without each endpoint inventing its own.

4. Transformers for entities you don't control. If you can't annotate a Doctrine entity, register a TransformerInterface for it (tagged in DI) and the transformer pool will apply it during serialization. Prefer this over hand-rolled toArray() methods.

5. Errors are a listener, not try/catch. Throw exceptions implementing the bundle's exception interface; a kernel.exception subscriber converts them (and symfony/validator violations) into a consistent error payload. Add new error types by implementing the interface, not by editing controllers.

6. Caching headers. View models implementing the cacheable interface get ETag/Last-Modified computed and 304 handling applied automatically.

Mapping to what you'd actually build in Laravel:

Bundle concept Laravel equivalent
Request-body DTO + deserialization FormRequest / spatie/laravel-data
View model + serializer groups JsonResource with conditional attributes
?view= group selection ?include= via spatie/laravel-query-builder
Paginated response contract ResourceCollection over paginate()
problem+json error listener bootstrap/app.php exception rendering
ETag / Last-Modified $response->setEtag() + middleware
Transformer pool Container-bound resources / Resource::collection

Gotchas and Tips

  • It is a wrapper of a wrapper. Two layers, two bug sources, one thin README. When behavior surprises you, bisect: reproduce with mediamonks/rest-api-bundle alone. Only then blame the kununu layer.
  • Maintenance risk is the headline risk. Zero dependents means no outside eyes, no issue traffic, no upgrade pressure. composer outdated will likely show it pinned to an old Symfony major. If you depend on it long-term, vendor/fork it and own the code.
  • ?view= is user-controlled. If group selection comes from the query string, an attacker can request a group you didn't intend to expose. Allowlist the accepted views in a request listener.
  • Group names are global strings. api:v1 in two unrelated view models collide silently. Namespace your groups per bounded context.
  • Deep object graphs serialize deeply. Bidirectional Doctrine relations will recurse or blow up payloads. Use transformers, @MaxDepth, or explicit group boundaries — and watch for the N+1 queries the serializer triggers.
  • Body param-converter edge cases. An empty body on POST often yields a null DTO rather than a validation error; a wrong Content-Type can be silently ignored. Add an explicit null check or a kernel.request guard.
  • Validation groups. Constraint violations map to your error format, but which constraints run depends on validation_groups. A DTO validated on Default will skip constraints you put in a named group — a class of bug that looks like "validation doesn't work."
  • Caching + auth is a footgun. Don't emit shared-cache headers on per-user responses; send Vary: Authorization and be conservative with the cacheable interface.
  • Exception listener ordering. The kununu subscriber may run before or after MediaMonks' — check getPriority(). A stray kernel.exception listener in your own app can swallow the JSON format and hand the client an HTML error page.
  • Debugging commands: bin/console debug:event-dispatcher kernel.exception, debug:router, and debug:container --tag=<transformer tag> to confirm your transformers and listeners are actually registered.
  • Extension points are clean: decorate the response builder, implement the view-model/exception interfaces, tag transformers, and use a kernel.response listener for cross-cutting headers (request ID, rate limits). Prefer these over subclassing.
  • Don't port the code to Laravel — port the contract. The valuable ideas (DTO in, view model out, explicit groups, problem+json, pagination as a contract) fit Laravel perfectly in ~200 lines with JsonResource and FormRequest. Copying the Symfony machinery gets you a second framework inside your first one.
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.
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
cgv/localized-resource