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

Liform Bundle Laravel Package

limenius/liform-bundle

LiformBundle generates JSON Schema from your Symfony forms, letting JavaScript libraries like liform-react render them client-side. It bridges server-side form definitions and modern frontend UIs, keeping validation rules and field structure in one place.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What the TPM is actually evaluating. Despite the "Laravel/PHP" filing, limenius/liform-bundle is a Symfony Bundle wrapping the framework-agnostic limenius/liform core. The bundle's value-add is Symfony-only: DI registration, a config tree, a controller/route exposing forms as JSON Schema, and Twig helpers. For a Laravel codebase the leverage is not the package as shipped — it is the concept and, at most, the core generator. A TPM should frame the decision as "do we adopt the pattern (server form/validation definition → JSON Schema as single source of truth), and is Liform a useful reference implementation or a dependency?"

Architecture fit.

  • As a bundle: no fit for Laravel. No Bundle system, no symfony/form, no Form Type tree to walk. Installing it means installing Symfony's form + DI stack into a Laravel app for a single purpose — heavyweight and in conflict with Laravel's own validator.
  • As a core library: partial fit. liform/liform is pure PHP and emits a portable JSON Schema artifact. That output portability is the only reason to consider it. The input contract (Symfony Form objects) is the blocker.
  • Direction of value. This converts a server-side definition into a machine-readable contract consumed by front-end form renderers (react-jsonschema-form, liform-react/vue, Formily), API docs, contract tests, and low-code form builders. In Laravel the equivalent source of truth is FormRequest rules + Validator, not Symfony Forms.

Integration feasibility (three paths, ascending cost).

  1. Standalone core, no bundle — composer require limenius/liform, feed it hand-built Symfony Form objects. Technically possible, practically awkward: pulls a heavy dependency that will not be used for anything else.
  2. Port the concept to Laravel — a thin service provider plus a rule→schema mapper over Illuminate\Validation\Rule and string rules. Estimate 2–4 weeks for a solid v1 covering required, string, integer, numeric, min/max, between, regex, in, nullable, array.*. Cost compounds for required_if/exclude_unless, nested arrays, and cross-field rules, which map poorly to JSON Schema.
  3. Build narrow, bespoke exporter — likely cheaper than a port if the requirement is a handful of forms and a fixed renderer.

Technical risk.

  • Ecosystem weight: 141 stars, 0 listed dependents, near-single-maintainer. March 2025 release is a positive liveness signal, but bus factor is ~1–2 and there is no downstream ecosystem to absorb bugs.
  • Spec drift: historical default is JSON Schema draft-04; draft-06/07/2020-12 differ on exclusiveMinimum, $defs vs definitions, and nullability. A renderer or validator pinned to another draft produces silent contract mismatches.
  • Version coupling: Symfony Form internals shift across majors (5→6→7). If we keep the bundle we inherit tracking Symfony majors despite not being a Symfony shop.
  • Opportunity score ~36 / low confirms this is a tactical utility, not a platform bet.

Key questions a TPM must get answered before committing.

  • Is the requirement "generate JSON Schema from our validation" or "generate JSON Schema at all"? If the latter, what is the source of truth — FormRequest, a config array, or a hand-authored schema?
  • Which JSON Schema draft must our consumer (renderer / validator / docs portal) support?
  • Do we need the full Symfony round-trip (rendered form + schema in lockstep), or only the schema artifact?
  • How many distinct form shapes exist, and how many use conditional or cross-field rules? High counts with heavy conditionals materially change the port estimate.
  • Is there a concrete second consumer today — a JS frontend, partner integration, docs portal, or form builder — or is this hypothetical?

Integration Approach

Stack fit: poor as delivered, workable as a concept extraction. The bundle targets PHP 8.x and Symfony 5.4–7.x. The PHP floor aligns with Laravel 10/11; the Symfony floor aligns with nothing in our stack. The honest framing to stakeholders: we are evaluating limenius/liform (the library), not limenius/liform-bundle — and on Laravel, even the library is a starting point, not a drop-in.

Migration path.

  1. Spike (≈1 week). In a scratch branch, install limenius/liform + symfony/form; model two representative forms (one flat, one with nested collections and a conditional) as Symfony Form types; generate schemas; validate against our target renderer and validator. This isolates whether the generator is good from whether a port is cheap.
  2. Decision gate. If the output shape is right but the Symfony input is wrong → port. If output quality is marginal → stop; the port cost is not justified.
  3. Port. Build a Laravel-native generator: ValidationRuleSet → SchemaObject, with an explicit handler per rule and a registry so unmapped rules fail loudly rather than being silently dropped. Reuse Liform's conceptual primitives (resolver/guesser-style interfaces) but not its Symfony-coupled classes.
  4. Parity harness. Golden-file snapshot tests: given a FormRequest, assert the emitted schema. Schema changes then surface as reviewable diffs.
  5. Consumers. Wire output into (a) a php artisan schema:dump command or dev-only /api/schemas endpoint, and (b) the front-end renderer. Keep it off the request hot path initially.

Compatibility notes.

  • Pin the JSON Schema draft explicitly as config; never rely on the generator default.
  • nullable in Laravel maps to absence from required plus a ["string","null"] type union — decide the convention once and test it; this trips most naive exporters.
  • Nested/array rules (items.*.name) need a recursive walker; Liform's collection handling is a useful reference.
  • If the bundle path is kept at all, isolate it behind a single adapter class so removal is a one-file change.

Sequencing. Spike → gate → port core generator → parity tests → first consumer (schema export command) → second consumer (front-end renderer) → retire hand-maintained schema files. Do not run the Symfony path and a Laravel path in parallel beyond the spike; dual sources of truth is precisely the failure mode this project exists to eliminate.

Operational Impact

Maintenance. The dominant ongoing cost is not the dependency — it is the rule-mapping surface. Laravel's validator has ~60 built-in rules plus custom Rule objects; each needs a mapping and a test. Budget maintenance proportional to the rules the API actually uses, and make unmapped rules a CI failure (throw, don't skip). Upstream: 0 dependents and a small maintainer base mean we should vendor-fork the core primitives we rely on, so an abandoned upstream is a non-event. A clean port also removes the obligation to track Symfony Form majors.

Support. No commercial support; community-only, low issue velocity at this star count. Name an internal maintainer explicitly. Liform's docs are thin — the codebase is the spec. Plan for the port team to read source, not documentation.

Scaling. Schema generation is CPU-bound but trivially cacheable: output is deterministic given a FormRequest class. Generate at build time (artisan schema:dump into a versioned artifact) rather than per request; then scaling is a non-issue. If generated at runtime, cache by class + version key and invalidate on deploy.

Failure modes to design against.

  • Silent rule drops — a new validation rule with no mapping produces a schema that under-describes the contract. Fail closed.
  • Spec drift — generator default draft diverges from the consumer's. Pin both sides; add a schema-validation test in CI.
  • Dual source of truth — hand-written schemas lingering after the generator ships. Remove them in the same release.
  • Conditional/cross-field gaps — required_if, exclude_unless, and polymorphic forms do not map cleanly; scope these out of v1 with an explicit, documented limitation rather than a wrong schema.
  • Upstream abandonment — mitigated by the fork posture above.

Ramp-up. Two distinct skills: (a) JSON Schema fluency and (b) the mapping from Laravel validation semantics to schema. The former is a few days for a competent engineer; the latter is learned by doing and captured in the golden-file suite. If the bundle/spike path is taken, add Symfony Form familiarity as a temporary cost. Realistic ramp: 1 week to a validated spike, 2–4 weeks to a production-grade v1 generator for common rules.

TPM recommendation. Treat this as a time-boxed spike, not an adoption — and note explicitly that the package does not apply to a Laravel target as shipped. The decision it supports is build a thin, owned schema exporter against Laravel validation, using Liform as a reference for output shape and collection handling, behind an internal interface so implementation is swappable. The upside — one form/validation definition instead of two, and elimination of client/server drift — is real and quantifiable; the license cost is zero and integration effort is low. The risk is maintenance on a niche, single-maintainer project, which the fork-and-own posture neutralizes.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
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