survos/liform-bundle
Survos Liform Bundle integrates Liform with Symfony to turn JSON Schema definitions into usable Symfony forms and Twig-rendered form UIs. It helps teams build schema-driven forms, keep validation and rendering aligned, and support dynamic data entry in admin tools and applications.
This is a Symfony bundle, not a Laravel package — so the honest "getting started" for a Laravel developer is: you will not drop this into a Laravel app. You either (a) run it inside a small Symfony service/microservice that Laravel calls over HTTP, or (b) pull in limen/liform directly with Symfony Forms compiled into a standalone kernel.
Minimal steps for the Symfony side:
composer require survos/liform-bundle
config/bundles.php.Resources/config for the service id and register it explicitly.FormType (a ContactType, UserType, etc.) and emit its JSON Schema:public function schema(FormInterface $form, LiformService $liform): JsonResponse
{
$schema = $liform->transform($form); // returns an array/object
return $this->json($schema);
}
The output is a JSON Schema document describing fields, types, required keys, and (partially) constraints. Consume it with react-jsonschema-form, @rjsf/core, jsonforms, or similar.
Where to look first: the bundle is thin — read limen/liform (the actual transformer) since that's where the behavior lives. The bundle is mostly wiring.
Schema-as-API-contract. Expose GET /forms/{type}/schema from Symfony. Laravel calls this, caches the payload, and hands the schema to a front-end renderer. This is the only pattern that makes sense given the stack mismatch.
Reuse admin/CRUD forms as the source of truth. If your team already maintains Symfony AbstractType classes for back-office CRUD, Liform turns them into renderable schema for free. This is the strongest value proposition: one definition, two consumers (server validation + client form rendering).
Schema + submit endpoint pairing. The generated schema only describes shape. Pair it with:
$form->submit($request->request->all())),Microservice bridge. Run a minimal Symfony app with just Forms + Liform. From Laravel:
$schema = Cache::remember("form.{$type}.schema", 3600, fn () =>
Http::get("http://forms-service/schema/{$type}")->json()
);
Schemas are deterministic per FormType + config, so cache aggressively and bust on form change.
Integration tips:
/v1/schema/{type}) since schema shape changes are breaking for clients.composer require symfony/form symfony/validator symfony/event-dispatcher. You will recreate a chunk of the container that Laravel does not provide.EventDispatcherInterface, OptionsResolver, Validator, and HttpFoundation in scope. Laravel's container won't satisfy them. Budget for a bridge/standalone kernel before you promise anything.react-jsonschema-form forks) differ in what they accept. Pin your client renderer against a captured sample schema before building UI on top.Constraint (custom validators, callback constraints, expression language) surfaces as a JSON Schema keyword. Treat the schema as structural, not a complete validation spec. Keep server-side validation authoritative.CollectionType, file uploads, and nested types produce nested object/array schemas. Verify these explicitly; nested form handling is the usual place generated schemas get thin or surprising.dd()) before JSON-encoding. If a field is missing, check the FormType's buildForm — unmapped or dynamically-added fields won't appear until the form is built.limen/liform directly and treat this bundle as a thin, optionally-vendored wrapper. Pin the version; the bundle's value is only service registration you can replicate in ~20 lines.services.yaml rather than fighting the container.How can I help you explore Laravel packages today?