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

rogerdsh/liform-bundle

A Symfony bundle that generates JSON Schema from Symfony forms, exposing form structure for client-side rendering and validation. Integrates Liform with Symfony to produce schema output for APIs and JavaScript form builders.

View on GitHub
Deep Wiki
Context7

Getting Started

First, be clear about what this package is: rogerdsh/liform-bundle is a Symfony bundle, not a Laravel package. There is no service provider, no facade, no config/liform.php. It wraps the liform/liform library (the Limenius project) so that a Symfony FormInterface can be serialized into a JSON Schema document. In a Laravel codebase you will not get day-to-day value from it directly — Laravel has no Form component to transform. It becomes relevant in three concrete situations:

  1. You maintain a Laravel app plus a Symfony admin/back-office service, and want both to emit the same schema contract.
  2. You are building a headless API where the frontend uses a JSON-Schema-driven form renderer (liform-react, react-jsonschema-form, Formily), and you want the schema generated from server-side validation rules rather than hand-written.
  3. You are migrating a Symfony app to Laravel and need to freeze the existing schema output before replacing it.

Minimal install (inside the Symfony side of your stack):

composer require rogerdsh/liform-bundle

Register it in config/bundles.php (Flex will usually do this):

return [
    // ...
    Lim\LiformBundle\LiformBundle::class => ['all' => true],
];

Then confirm the container actually has the service before writing any code:

bin/console debug:container liform
bin/console debug:container --tag=twig.extension | grep -i liform

First use case: take one existing form type and dump its schema from a controller.

// src/Controller/SchemaController.php
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\Form\FormFactoryInterface;

public function schema(FormFactoryInterface $forms): JsonResponse
{
    $form = $forms->create(RegistrationType::class);

    return new JsonResponse($this->liform->transform($form));
}

If you are on the Laravel side, the equivalent first move is to not install the bundle: install liform/liform standalone, and build the Symfony\Component\Form\FormFactory via symfony/form + symfony/validator wired by hand. That is more code than it sounds, which is the honest reason most Laravel teams skip this and use opis/json-schema or a hand-maintained schema file instead.

The very first thing to check before investing: the fork's composer.json — its require block for symfony/form, php, and liform/liform. With 0 stars and 0 dependents this is an unmaintained fork; pin it to an exact version or a commit hash, and vendor-review the diff against upstream limenius/liform-bundle.

Implementation Patterns

Pattern 1 — Schema endpoint as the single source of truth. Expose one route per form type, cache the result, and let the SPA fetch it.

#[Route('/api/schema/{form}', methods: ['GET'])]
public function show(string $form, FormFactoryInterface $forms, CacheInterface $cache): JsonResponse
{
    $schema = $cache->get('schema.'.$form, function () use ($forms, $form) {
        $map = [
            'registration' => RegistrationType::class,
            'checkout'     => CheckoutType::class,
        ];
        return $this->liform->transform($forms->create($map[$form]));
    });

    return new JsonResponse($schema);
}

Note the whitelist — never accept a class name from the request, since create() will instantiate anything.

Pattern 2 — Twig-side embedding. If the Symfony app renders pages, the bundle's Twig extension lets you embed the schema inline and boot the JS renderer from it:

<script>
  window.__SCHEMA__ = {{ liform(form) }};
</script>

Verify the exact function/filter name with bin/console debug:twig | grep -i liform — this is the single most common source of "it does nothing" reports on these forks.

Pattern 3 — Constraint-driven schemas. The real leverage is that your existing Symfony Validator constraints become required, minLength, pattern, enum, etc. Put validation on the DTO/entity, not the form type, so both the HTML form and the JSON Schema inherit it:

class RegistrationInput
{
    #[Assert\NotBlank]
    #[Assert\Email]
    public string $email;

    #[Assert\Length(min: 12, max: 128)]
    public string $password;
}

Then data_class on the form type. This is the Symfony analogue of Laravel's FormRequest rules — and it is the piece a Laravel dev should port conceptually: one rules definition, two consumers (server validation, client schema).

Pattern 4 — Submitting against the schema. The bundle only produces schemas; submission still goes through normal Symfony form handling. Keep it that way. Do not try to feed the JSON Schema back into the server as validation — validate with the form/validator as usual, and treat the schema as a client hints document only.

Pattern 5 — Bridging into Laravel. If you must consume this from Laravel, treat the Symfony service as external and hit it over HTTP (Pattern 1) rather than trying to boot the bundle in-process. Cache the schema in Laravel with Cache::remember() keyed by form name plus a schema version, and validate the cached payload with json_decode(..., flags: JSON_THROW_ON_ERROR) plus a opis/json-schema self-check before serving.

Pattern 6 — Custom field mapping. When a custom form type renders as a useless {"type": "string"}, register a transformer rather than patching the bundle. That is the intended extension point; the bundle's config typically accepts a list of transformer services. Check bin/console config:dump-reference liform for the exact keys on this fork — the config tree is where forks diverge most.

Gotchas and Tips

  • Namespace and package name mismatch. Forks frequently keep the upstream namespace (Lim\LiformBundle) while changing the Packagist name. composer require rogerdsh/liform-bundle may succeed while RogerDS\LiformBundle\... does not exist. Always trust composer show -a rogerdsh/liform-bundle and the autoload.psr-4 block, not the repo name.
  • Not on Packagist. With 0 dependents there is a real chance you need a VCS repository entry:
    "repositories": [{ "type": "vcs", "url": "https://github.com/RogerDS/LiformBundle" }]
    
    and pin "rogerdsh/liform-bundle": "dev-master#<sha>".
  • Unmaintained-fork risk. Zero stars, zero dependents, MIT license, no release cadence. Budget for vendoring it or forking it into packages/. Never let a transitive composer update move it.
  • JSON Schema draft drift. The output is almost certainly draft-04 era. Modern renderers (react-jsonschema-form v5+, Formily) expect draft-07/2020-12 and will silently ignore dependencies, const, or exclusiveMinimum-as-number. Normalize on the client or post-process the array before serving.
  • Caching must key on more than the form name. If a form type reads the authenticated user, locale, or feature flags, a shared cache key leaks schema between users. Include those in the key or bypass the cache.
  • required is derived from NotBlank/NotNull, not from PHP nullability. A nullable typed property with no constraint is optional; a non-nullable one is not automatically required in every version. Assert explicitly.
  • Choice fields. ChoiceType maps to enum with the labels, not the values, in some configurations. Verify with a scratch controller before shipping — this mismatch breaks SPA submits and is a classic footgun.
  • File uploads and DateTimeType generally degrade to opaque strings. Handle them with custom transformers, or accept a hand-written schema fragment merged over the generated one.
  • Debugging technique: dump the raw array, not the response.
    dump($this->liform->transform($form)); // look for empty "properties": []
    
    An empty properties array almost always means data_class is missing on the form type.
  • No Laravel integration, ever. Do not write a service provider around this. If the goal is "generate JSON Schema from Laravel validation rules," the pragmatic path is a small custom FormRequest-to-schema mapper (loop $request->rules(), switch on rule string) — a few hundred lines, fully owned, no Symfony dependency. Evaluate that before adopting this bundle into a Laravel project.
  • Extension point to prefer: custom transformers over editing vendor code. Fork cost is low here precisely because the surface is thin — if you find yourself patching more than one file, fork it into your monorepo instead.
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.
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource