bgaze/bootstrap-form
bgaze/bootstrap-form is a Laravel package that generates Bootstrap-ready forms through a fluent PHP API. It handles model binding, validation errors, old input, labels, help text, and layout classes, so you can build accessible, styled forms without writing repetitive HTML markup.
Architecture fit. This is a Laravel Blade form-builder package (facade BF::* plus <x-bf::*> components) whose content sinks — label, help, success, prepend/append, Bootstrap 4 custom-file text — intentionally emit raw HTML so call sites can inject markup. v4.2.0 adds an escape setting that follows the package's existing config → form → field cascade and defaults to false. That is architecturally consistent with how every other option in this package resolves, and it is opt-in: existing rendering is byte-identical unless a team opts in.
Integration feasibility. Low-friction. A composer update is sufficient to consume the release; no code changes are required to stay on prior behavior. The meaningful work is not integration but audit: identifying which sinks receive user input, database values, or translation strings today, because those are unescaped at the sink regardless of this setting. The release notes are explicit that this is not boundary escaping, and that framing should drive the rollout plan rather than the version bump.
Technical risk.
escape => true globally and concluding XSS is handled. The docs state the opposite; the setting only affects sink rendering of values that are already strings. Boundary escaping remains the application's job.Htmlable/Blade slot will render as literal tags once escape => true is set at config level. The Htmlable opt-out preserves component slots, but string-concatenated markup will break.°C, raw when a tag appeared). Any call site that depended on that implicit behavior changes when escape => true is set. This is the intended fix, but it is a behavior change at the call site, not just a new flag.escape="false", switch, inline, custom, show-all-errors, show-valid-feedback, disable-errors now read only "true"/"false". Previously escape="false" was truthy and enabled the setting. Anyone who passed escape="false" to disable escaping was silently getting escaping; after upgrade they get the behavior they wrote. That is a fix, but it is a rendering change for those call sites. String-valued settings (help="false") are unaffected.required_mark, validation messages, and standalone BF::label() are outside the setting. BF::label() has its own per-call argument and will not honor a global escape — a consistency trap worth documenting internally.Key questions.
escape="false" or any of the affected boolean attributes as strings, and are they covered by tests?escape => true at config level, or do we need per-form rollout? Per-field only would be unmanageable at scale.Htmlable/HtmlString (safe under global escape) or raw strings (will break)?Stack fit. Laravel + Blade + Bootstrap 5 (Bootstrap 4 rendering frozen). The config cascade (config → form → field) means the setting can be adopted at whatever granularity the codebase tolerates, including a single form for a pilot.
Migration path. No mandatory migration. Bump the constraint, run the suite, ship. Then treat escaping as a deliberate hardening project rather than part of the upgrade: audit sinks, convert intended markup to Htmlable/Blade slots, then flip the config default.
Compatibility.
escape => false preserves current rendering, so the upgrade itself is non-breaking."false" to a boolean setting.BF::label() no longer throws TypeError on an HtmlString — strictly additive.required_mark, validation messages, and standalone BF::label() are unaffected; document that internally so nobody assumes uniform behavior.Sequencing.
escape=, switch=, inline=, custom=, show-all-errors=, show-valid-feedback=, disable-errors= string literals and clean up any "false" workarounds.Htmlable or Blade slots so it survives a global opt-in.escape => true at config level (or per form as an intermediate step) and re-run visual regression.Maintenance. Low steady-state cost. The setting is configuration, not code, and the cascade matches how the package already resolves options. The ongoing burden is documentation discipline: teams must know that escape governs sink rendering only, and that BF::label() and required_mark sit outside it.
Support. Expect questions of the form "we turned on escape, why is our label showing <b>?" and "we turned on escape, why is XSS still possible?" Both are answered by the docs, but both will be asked. A short internal note covering the escape-vs-boundary distinction, the Htmlable opt-out, and the affected boolean attributes will absorb most of it.
Scaling. Negligible runtime cost — escaping at render is cheap relative to the templating already happening. The scaling concern is organizational: per-field opt-in does not scale past a handful of forms, so the end state should be a config-level default with Htmlable exceptions, not scattered ['escape' => true] arrays.
Failure modes.
escape => true with string-built markup in labels/addons → visible tag leakage on customer-facing forms."false" string passed to a boolean setting flips meaning post-upgrade → unexpected toggling of switch, inline, custom, error/feedback display.BF::label() honors the global setting → escaping applied in one place and not another in the same view.Ramp-up. Consumer-side ramp-up is near zero: install, read the two docs sections, no code changes. Engineering-lead ramp-up is roughly half a day to inventory sinks and grep the affected attribute names, plus the time to convert intended markup to Htmlable. A pilot on one form with escape => true is a reasonable way to validate the conversion pattern before flipping the config default.
How can I help you explore Laravel packages today?