pear/html_quickform2
HTML_QuickForm2 is a PHP library for creating, validating, and rendering HTML forms, with server-side and client-side validation, multipage wizards, and pluggable elements and renderers.
Architecture fit. HTML_QuickForm2 is a self-contained, front-controller-agnostic form object model: you construct elements, attach filters/rules, validate, and __toString() the result. That is orthogonal to Laravel's architecture rather than aligned with it. It has no service provider, no facade, no container bindings, no config publishing, and no contracts — everything is instantiated directly (new HTML_QuickForm2('name')). It predates PSR-4 (underscore class names, HTML_QuickForm2_Element_*), so it will never feel idiomatic next to Illuminate\Validation or Blade components. Fit is best described as "usable inside a Laravel render path," not "integrated with Laravel."
Where it genuinely fits. Only three scenarios justify adoption:
Where it does not fit. Anything using Livewire, Inertia, Filament, Vue/React form stacks, or Laravel's validation/authorization pipeline. QF2 would become a duplicate validation engine running in parallel to FormRequest, which is a net architecture negative.
Integration feasibility. Composer installation is clean (composer require pear/html_quickform2:^2.5.0), autoloading is PSR-4-compatible via Composer since 2.1, minimum PHP is 7.1, and v2.5.0 is verified deprecation-free on PHP 8.5/8.6. That means a working prototype is roughly 1–3 engineering days. The real cost is not installation but the adapter layer you must write and own forever:
DataSource adapter that pulls from Illuminate\Http\Request / $request->old() so repopulation works after validation failure.addElement('hidden', '_token', csrf_token())) — no @csrf equivalent, and no automatic _method spoofing.Validator::make(), otherwise business rules live in two places.Technical risk. The dominant risk is ecosystem fragility, not code quality. 23 stars and 0 dependents means no downstream safety net: nobody else will find the edge cases for you, and there is effectively no third-party knowledge base, no Stack Overflow corpus, and no Laravel community recipes. Release cadence appears driven by PHP deprecation hygiene (v2.3.0 → 2.5.0 are PHP 8.1/8.4/8.5/8.6 compatibility releases, plus Psalm bumps) rather than by feature demand — good for stability, but it also signals a maintenance-mode project with volunteer capacity behind it. HTML5 element support is still "planned," so native email, number, date, color, and file-input ergonomics are on you. Output is HTML strings, so escaping correctness for labels, attribute values, and static content becomes an application-level security concern you must verify rather than assume. The bundled JavaScript validation library is self-contained and framework-free, which is a plus for conflict-freedom but a minus for CSP compliance and for teams standardising on Alpine or Livewire's JS.
Key questions to resolve before any commitment:
Stack fit. Adopt only where the delivery model is server-rendered HTML returned in a full response — classic Blade controllers, no SPA hydration, no Livewire re-render loops. QF2's model assumes one request builds the form, one request validates and re-renders; that maps well to a POST-redirect-GET flow but poorly to partial updates.
Compatibility matrix.
| Layer | Constraint / note |
|---|---|
| PHP | ≥ 7.1; clean on 8.1–8.6. Pin Laravel's PHP floor to 8.2+ and you are safe. |
| Laravel | 9–12 fine at runtime; no first-party bindings at any version. |
| Composer | Standard pear/html_quickform2:^2.5.0; low transitive footprint. |
| Front-end | Bundled vanilla JS validator; conflicts unlikely, CSP needs a nonce if you inline it. |
| PHPUnit | Do not treat upstream's upgraded polyfills as a signal your app broke; deprecation checks in your suite may newly fire. |
Isolation boundary (non-negotiable). Do not let HTML_QuickForm2_* classes leak into controllers or domain code. Wrap them:
// app/Forms/QuickForm/FormFactory.php — the only files that reference QF2
$form = $this->qf->make('profile'); // returns HTML_QuickForm2
$form->addDataSource(new LaravelOldInputSource($request));
Expose a small application-facing contract (FormBuilder::build(string $key, array $context): FormView) so the vendor can be swapped for a Blade component set later without touching call sites. Ship it as a private Composer package, not a composer.json entry in the monolith.
Migration path (from HTML_QuickForm v1). Use upstream's migration guide as the checklist; migrate element-by-element against a golden-file test that asserts rendered HTML and validation outcomes for a fixed input matrix. Expect the friction points to be renderer markup changes, rule signature changes, and the loss of HTML_QuickForm_Controller semantics.
Migration path (greenfield / from Blade forms). Do not migrate. Run a bounded parallel pilot instead.
Sequencing.
FormRequest reference implementation, and no JS console errors.FormFactory, LaravelDataSource, Renderer plugin, CSRF middleware hook, error-message mapping into the app's flash/error bag conventions.Delivery shape. Treat the adapter as an internal product with a versioned README and example forms; the failure mode of these evaluations is that one engineer's prototype becomes an undocumented dependency that nobody else can modify.
Maintenance. Steady-state cost is low but nonzero and entirely yours: adapter, renderer, and element subclasses must be re-verified on every PHP minor and every Laravel major. Upstream's own releases are compatibility-driven, so they will usually help — but they also mean the package is in maintenance mode, and there is no commercial backer to escalate to. Budget ~1–3 engineer-days per PHP minor and ~3–5 days per Laravel major for regression testing of the adapter.
Support model. Community-only: GitHub issues plus the PEAR bug tracker. No SLA, no security advisory programme you can subscribe to in the way you would for Symfony or Laravel packages. Your internal security review must own escaping/XSS verification and dependency CVE triage. With 23 stars and 0 dependents, expect low issue throughput — file a patch upstream if you need it, and assume you may have to fork.
Scaling characteristics.
Failure modes and mitigations.
| Failure mode | Impact | Mitigation |
|---|---|---|
| PHP minor adds a deprecation in a custom element/validator you wrote | Notice spam, potential fatal under strict error handlers | Run php -d error_reporting=E_ALL artisan serve in CI; forbid $array[null] = and spl_object_hash() in app code |
Validation logic duplicated between QF2 rules and FormRequest |
Silent drift; server accepts/rejects inconsistently with client | Single source of truth: pick one. Prefer Laravel rules; use QF2 only for rendering |
| Renderer markup drifts from design system on upgrade | Broken layout, failing visual tests | Pin vendor version; golden-file tests on rendered HTML |
| Escaping regression surfaces user content unescaped | XSS | Explicit htmlspecialchars() on any value interpolated post-exportValues(); escaping audit in the pilot gate |
| Bundled JS conflicts with Alpine/Livewire/CSP | Broken client validation, console errors, blocked scripts | Disable client validation for forms inside interactive components; nonce the script tag |
| Upstream goes dormant | No fixes for future PHP versions | Adapter boundary + documented in-house fork procedure; low LOC to patch |
pear/html_quickform2 removed from Packagist |
Build breaks | Commit a lockfile, mirror the package internally, or vendor a fork |
Ramp-up. A mid-level Laravel developer needs roughly 1–2 weeks to become productive: the API is small but undocumented outside the PEAR manual, class names are un-idiomatic, and there are no modern tutorials. That is materially worse than Blade components (~1 day). Plan for one designated owner and a 60–90 minute internal walkthrough plus three canonical example forms checked into the repo. Onboarding cost is the strongest argument against adopting this for a growing team — it converts a solved problem into tribal knowledge.
Net TPM position. Low-adoption, maintenance-mode, non-idiomatic dependency with a real but narrow niche (QF1 migration, imperative dynamic forms). Given 23 stars and zero dependents, it is not a strategic bet. Fund the 2–3 day spike only where a concrete driver exists; default the rest of the estate to Laravel-native forms and keep QF2 behind an adapter so the exit cost stays measured in days, not quarters.
How can I help you explore Laravel packages today?