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

Form Error Log Bundle Laravel Package

oh/form-error-log-bundle

A Symfony bundle that records form validation errors for easier debugging and monitoring. It captures error details from failed submissions so you can trace issues, inspect patterns, and keep user-facing responses clean.

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package. If you're coming from Laravel, you cannot composer require it into a Laravel app and expect it to work — you'd either need a Symfony application or replicate the pattern (a listener on validation failure that writes to a dedicated log channel).

For a Symfony app:

  1. Install: composer require oh/form-error-log-bundle
  2. Register the bundle in config/bundles.php (Flex may do this automatically):
    Oh\FormErrorLogBundle\OhFormErrorLogBundle::class => ['all' => true],
    
  3. Look first at DependencyInjection/Configuration.php and Resources/config/services.xml in the vendor directory. Those two files tell you the exact config keys, the logger service ID, and which form events are hooked. Don't guess from the README alone.
  4. Minimal first use case: enable it in dev/staging, submit an intentionally invalid form, and confirm entries appear in your configured Monolog channel. Expected config shape (verify against Configuration.php):
    # config/packages/oh_form_error_log.yaml
    oh_form_error_log:
        channel: form_errors
        level: warning
    
  5. Create/route the channel in config/packages/monolog.yaml so form errors go to a separate file rather than muddying app logs.

The first practical win: instead of grepping var/log/dev.log for "This value is not valid", you get a structured record with the form class, field path, and message — per submission.

Implementation Patterns

Dedicated Monolog channel per environment. Route form-error logs to var/log/form_errors.log in staging and a sampled handler in production. Validation failures are user-error noise, not application errors — keep them out of your alerting channel.

Subscriber-level filtering. The bundle's subscriber likely fires on FormEvents::POST_SUBMIT and inspects $form->isSubmitted() && !$form->isValid(). If you need more control (ignore specific form types, only log first N errors, skip login/registration forms), decorate or replace the subscriber rather than patching vendor code:

final class FilteredFormErrorLogger
{
    public function __construct(private LoggerInterface $logger) {}

    public function onPostSubmit(FormEvent $event): void
    {
        $form = $event->getForm();
        if ($form->isRoot() || !$form->isSubmitted() || $form->isValid()) {
            return;
        }
        foreach ($form->getErrors(true) as $error) {
            $this->logger->warning('form_error', [
                'form'   => $form->getConfig()->getType()->getInnerType()::class,
                'field'  => $error->getOrigin()?->getName(),
                'message'=> $error->getMessage(),
            ]);
        }
    }
}

Structured context, not string concatenation. For day-to-day usefulness you want queryable fields: form class, error origin, error message, request ID/correlation ID, user ID (if available), and environment. Monolog's JSON formatter + a log aggregator makes this searchable.

Pair it with a request-scoped correlation ID. A Monolog processor that injects a request ID makes form-error logs joinable to the same request's other logs — far more useful than isolated entries.

Testing hook. In a functional test, replace the logger with a spy and assert a record was emitted for an invalid submission. In a Laravel port, do the equivalent with Log::spy() inside a FormRequest failure test.

Laravel equivalent if you're not on Symfony. There's no drop-in; the same idea is ~15 lines in App\Exceptions\Handler or a ValidationException listener:

Event::listen(ValidationException::class, function ($e) {
    Log::channel('form_errors')->warning('form_error', [
        'route' => request()->route()?->getName(),
        'errors'=> $e->errors(),
    ]);
});

Use this as the reference model for what the Symfony bundle is doing.

Gotchas and Tips

  • Symfony vs Laravel mismatch is the biggest gotcha. The package name (...Bundle) and the Resources/config layout are Symfony conventions. Installing it in Laravel will fail service registration. Treat it as a reference implementation, not a dependency.
  • Nested forms and collections duplicate errors. Calling $form->getErrors(true) on a parent and again on each child produces the same message multiple times. Decide whether you log per root form or per field origin, and stick to one. If the bundle logs both, add a dedupe guard in a decorator.
  • Never dump $form->getData() blindly. Password fields, API keys, and PII routinely live in form models. Log field names and error messages; scrub or omit values.
  • Expected validation failures are not error-level events. Log at warning or info. Logging every failed login at error will page someone at 3 a.m. and destroy your signal-to-noise ratio.
  • Disable or sample in test and production. In test env, form errors during fixtures/tests will spam logs; in production, a bot hammering a public form can fill disks. Use fingers_crossed or a sampling handler.
  • Low adoption = vendor risk. 5 stars, 0 dependents, no visible activity means you should pin the exact version in composer.json, read the full source before relying on it (it's small), and be prepared to fork or replace with your own ~30-line subscriber. Don't build critical alerting workflows on top of it.
  • Debugging service wiring: bin/console debug:container --tag=kernel.event_subscriber | grep -i form and bin/console debug:event-dispatcher Oh\\FormErrorLogBundle\\... will confirm whether the listener is actually registered. If nothing logs, the event subscription or the Monolog channel config is almost always the cause.
  • Extension points to prefer: a custom Monolog processor for shared context, a decorator around the bundle's logger service, or a replacement subscriber. Avoid editing vendor/ — a composer update will erase it.
  • Config key names drift. This bundle is small enough that a patch release could rename a config key; keep your config in one file and add an integration test that submits an invalid form and asserts the log line, so an upgrade failure is caught immediately rather than in production.
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