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

Symfony Entry Contract Bundle Laravel Package

intellect-web-development/symfony-entry-contract-bundle

Symfony bundle for defining and enforcing entry contracts, helping standardize how incoming data is validated and handled. Keeps controllers lean, centralizes contract rules, and integrates cleanly into Symfony applications.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle (not a Laravel package), so treat it as a config/bundles.php citizen rather than a service provider. Because the package has zero stars, zero dependents, and no ecosystem footprint, your first job is verification, not integration.

Minimal steps:

  1. Inspect before installing. Clone the repo and read, in order: README.md, composer.json, src/, and tests/. With no dependents there is no external signal on quality — the source is the only documentation you can trust. Confirm the PHP and symfony/* version constraints actually match your app (a bundle built against Symfony 5.x will not boot on 6.4/7.x without deprecation noise).
  2. Install pinned. composer require intellect-web-development/symfony-entry-contract-bundle:^<exact> — never a floating constraint on a package this young. Commit composer.lock in the same PR.
  3. Register the bundle in config/bundles.php:
    return [
        // ...
        Intellect\SymfonyEntryContract\SymfonyEntryContractBundle::class => ['all' => true],
    ];
    
    Then bin/console cache:clear and bin/console debug:container --tag=<whatever tag the bundle exposes> to see what it registered.
  4. Look for the extension point first. Find the attribute, interface, or base class the README calls a "contract." That single class is where 90% of your day-to-day usage will live — everything else in the bundle is plumbing around it.

First use case: pick one noisy controller action — ideally one with hand-rolled request validation and a wall of if (!$valid) { return $this->json([...]) }. Replace it with a declared entry contract and observe the "pretty" error output the description advertises. If the error rendering is not visibly better than Symfony's default ConstraintViolationList serialization, the package is not earning its dependency.


Implementation Patterns

Contract-per-entry-point. The name suggests the intended model: a contract object describes what a given entry point (controller action, console command, message handler) accepts. Model it as one class per action, not one god-contract per controller — that keeps the "pretty" error messages scoped to the fields the caller actually sent.

Attribute-first, config-second. Bundles that advertise "pretty contracts" almost always ship a PHP attribute you place on the controller method. Prefer the attribute over YAML/XML config: it survives refactors, shows up in IDE navigation, and keeps the contract next to the code it guards. Reserve config files for global switches (enable/disable in dev, error format toggles).

Validation delegation. Assume the bundle wraps or composes Symfony's Validator. Do not duplicate constraints in both your DTO and a separate contract definition — pick one home. If the bundle's contract is the DTO, let the bundle own the constraints; if it's a wrapper, keep constraints on the DTO and let the bundle only handle extraction and rendering.

Error rendering as a middleware concern. "Pretty contracts" implies the bundle hooks the kernel exception flow to format violations. Wire it so it only activates for the content types you care about (application/json, application/problem+json). Use Symfony's Problem Details (RFC 7807) as the target shape if the bundle supports it — clients integrate against it more easily than a bespoke JSON shape.

Testing pattern. Write one functional test per contract:

$client->request('POST', '/orders', [], [], ['CONTENT_TYPE' => 'application/json'], json_encode(['qty' => -1]));
$this->assertResponseStatusCodeSame(422);
$this->assertJsonPath('violations.0.propertyPath', 'qty');

Assert on the stable parts of the payload (status code, property path, error code), not on human-readable messages. Message wording is the thing most likely to change on a patch release of a package with no release discipline yet.

Integration tip — boundaries. Contracts belong at system boundaries: HTTP in, console in, message-queue in. Do not push entry contracts onto internal service calls; Symfony's container + typed constructor args already cover that, and you'll end up with contract objects that exist only to satisfy a bundle.


Gotchas and Tips

Zero dependents is a real risk, not a formality. You will not find StackOverflow answers, GitHub issues, or blog posts when it misbehaves. Budget for reading the bundle's src/ yourself, and consider forking under your org namespace with a replace entry if you adopt it in production. Pin the version and treat every upgrade as a code review of the bundle's diff.

Release date is in the future relative to most "current" baselines. Verify the published version actually exists on Packagist (composer show intellect-web-development/symfony-entry-contract-bundle --all) before assuming the tag is installable. A missing or malformed tag will surface as an opaque "could not find package" error.

Bundle registration order matters more than you'd expect. If the bundle registers a kernel exception listener or a request transformer, it competes with your existing ExceptionListener, API Platform's error handler, or a FOSRestBundle-era listener. Symptom: your new "pretty" errors are silently replaced by the old format. Debug with bin/console debug:event-dispatcher kernel.exception and check the listener priority.

Attribute autoloading and cache. Attribute-driven bundles read class metadata, which is cached. After adding a contract attribute, run bin/console cache:clear in dev. A missing cache:pool:clear cache.app step is the usual reason a new contract "doesn't do anything."

Contract resolution failures look like 500s, not 422s. If the bundle can't find or instantiate a contract class, the exception may propagate as a server error. Add a functional test that asserts the happy path returns 200 and the violation path returns 422 — a passing happy-path test alone won't catch a broken contract binding.

Check the error shape early. Decide whether you accept the bundle's default JSON shape or need to override it with a custom normalizer/formatter. Changing the shape after mobile clients ship is expensive. If the bundle exposes a formatter interface, implement it before you have consumers.

Extension points to look for (in order of usefulness): a formatter/normalizer interface for error output; a contract resolver interface for custom instantiation; a config tree node for enabling/disabling per-environment; a tagged service for registering contract types. If none of these exist, the bundle is closed for extension and you should weigh that against writing ~80 lines of kernel.exception listener yourself — which is often the honest alternative for a "pretty contracts" feature.

Dev-only first. Enable it behind when@dev / when@test in config/bundles.php for a sprint. If it survives real usage and you've actually read the source, promote to all.

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