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

Vanio Api Bundle Laravel Package

vanio/vanio-api-bundle

Vanio API Bundle offers a structured foundation for building APIs in PHP applications, with reusable components for endpoint configuration, request handling, and response serialization. It integrates with existing frameworks to simplify consistent API development.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install and register. This is a Symfony 2/3-era bundle, so registration differs from modern Symfony:

composer require vanio/vanio-api-bundle
// app/AppKernel.php (Symfony 2/3)
$bundles = [
    // ...
    new Vanio\ApiBundle\VanioApiBundle(),
];

// Symfony 4+/5+: config/bundles.php
return [
    Vanio\ApiBundle\VanioApiBundle::class => ['all' => true],
];

If the package ships routes (check Resources/config/routing.xml or routing.yml), import them; if not, skip routing entirely — most of this bundle's value is in services and listeners, not HTTP endpoints.

2. Know where to look first. The README for a 1-star bundle is thin, so treat the source as the documentation, in this order:

File Why it matters
DependencyInjection/Configuration.php The authoritative config schema — every key you can set under vanio_api:
DependencyInjection/VanioApiExtension.php How config maps onto services; reveals defaults
Resources/config/services.yml Service IDs, tags, and decoration points
EventListener/ (or Subscriber/) The behaviour you actually get for free (likely exception → JSON response, request body deserialization)
composer.json PHP/Symfony version constraints — the single biggest install risk

3. First use case: typed request bodies. The core promise of a bundle like this is "POST JSON in, controller argument out, errors in one consistent shape." Start with the smallest possible endpoint:

// src/AppBundle/Api/CreateOrderRequest.php
class CreateOrderRequest
{
    /** @var string */
    public $customerId;
    /** @var int */
    public $quantity;
}

// src/AppBundle/Controller/OrderController.php
public function createAction(CreateOrderRequest $request)
{
    // dump($request); exit;  <-- verify it actually populated before writing more
    return ['customerId' => $request->customerId];
}

Send a malformed body with curl -X POST -H 'Content-Type: application/json' -d '{"quantity":"abc"}' and observe what comes back. That single test tells you whether validation, deserialization, and error formatting are all wired — before you build anything on top of them.

Implementation Patterns

DTO-per-endpoint. Don't reuse entities as controller arguments. Use one input class per action; it makes validation rules explicit, keeps your mapping layer out of controllers, and means a schema change is a one-file diff. Where the bundle's deserializer is too magic, fall back to symfony/serializer with explicit ->deserialize($json, Foo::class, 'json') — you keep the typed controller signature without depending on undocumented behaviour.

Uniform error envelope. The bundle's exception handling is the piece you'll want to standardise. Pick a shape and enforce it everywhere:

{ "error": { "code": "validation_failed", "message": "...", "details": { "quantity": ["Must be positive."] } }

If the built-in listener doesn't match, register your own kernel.exception listener and give it a lower priority than the bundle's so you can control the output — or decorate the bundle's service ID rather than editing vendor code.

Validation as a first-class step. Wire the DTO into Symfony's Validator via constraints or a validation.yml mapping. In Laravel terms this is your FormRequest; the difference is that Symfony won't auto-validate a controller argument, so the check belongs in an explicit layer (a listener, a param converter, or a small base controller helper).

Versioning and content negotiation. Keep it boring: /api/v1/... prefix, Accept: application/json enforced, and a single json_encode flag set (JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) applied in one place. Avoid per-controller serialization calls — that's where inconsistent payloads creep in.

Testing. Use WebTestCase and assert against decoded arrays, not raw strings, so key ordering and whitespace never break the suite:

$client->request('POST', '/api/v1/orders', [], [], ['CONTENT_TYPE' => 'application/json'], $json);
$this->assertSame(422, $client->getResponse()->getStatusCode());

Also add one test per error branch of the exception listener — that component is the one most likely to silently swallow something.

Laravel-to-Symfony mapping if you're porting muscle memory: FormRequest → DTO + Validator; Handler::render → kernel.exception listener; API Resource → Serializer with groups; middleware → event subscribers.

Gotchas and Tips

Maintenance is the headline risk. One star, zero dependents, a Symfony2-era description. Expect PHP 8 fatal errors from old type hints, deprecated ContainerAware, and getMock()-style test code. Before committing, run composer install against your actual PHP version — not the docs' version — and read the constraint line in composer.json. If it fights you, vendor the one or two classes you actually need and drop the dependency.

Config keys are not documented. Anything you set under vanio_api: must be traced to Configuration.php. Symfony silently ignores unknown keys only in some setups; more often you'll get a confusing InvalidConfigurationException three layers deep. When in doubt: bin/console config:dump-reference vanio_api.

Debug the container, not the code. Old bundles rely on tags and compiler passes that modern autowiring won't pick up:

bin/console debug:container --tag=vanio_api.something
bin/console debug:container vanio_api.service.id
bin/console debug:event-dispatcher kernel.exception

If deserialization "does nothing," the listener is usually registered but not tagged, or its priority puts it after your controller's param converter.

The {} vs [] trap. An empty DTO serializes to [] unless it implements \JsonSerializable or is normalized as an object. Clients parsing response.customer.id will break. Force object casting in your normalizer, or return associative arrays from controllers and let one encoder handle it.

Date and scalar coercion. A JSON deserializer that maps "2024-01-01" onto a \DateTime property will either work perfectly or throw a 500 depending on the bundle's normalizer registration — verify with a real payload. Same for int vs string from form-encoded requests; test both application/json and x-www-form-urlencoded if you accept both.

Prod swallows, dev screams. Exception listeners frequently branch on kernel.debug. An error that renders a full stack trace locally may become a bare 500 with an empty body in prod. Test with --env=prod at least once before shipping.

Content-Type strictness. These bundles typically reject requests missing the JSON content type with a silent empty body rather than a 415. Make the failure explicit in your own listener; a client sending text/plain should get a clear message, not an empty DTO.

Best extension points, in order of safety: (1) decorate an existing service, (2) add an event subscriber with explicit priority, (3) override a template/route, (4) fork a class. Never patch vendor/ — with zero maintainers you'll be carrying that diff forever. If you outgrow the bundle, the exit path is short: replace the deserializer with symfony/serializer and the error listener with a 40-line kernel.exception subscriber. Budget for that from day 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.
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
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons