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

Reform Laravel Package

ruwork/reform

ruwork/reform is a Laravel/PHP package for defining forms as reusable objects, mapping request data, validating input, and transforming it into typed values. It helps keep form handling organized, consistent, and testable.

View on GitHub
Deep Wiki
Context7

Getting Started

Reform is a Symfony-oriented form helper package from the Ruwork/Ruvent family. It is intended to sit alongside symfony/form and reduce the boilerplate you normally write when binding a form to a typed PHP object.

Minimal setup:

  1. Install it next to a working Symfony app and the Form component:

    composer require ruwork/reform:^0.2
    

    The latest tagged release is 0.2.1, a patch that explicitly fixes compatibility with Symfony 4.1.2. That is a strong signal about the supported target line: this package is built for Symfony ~4.1, not 5/6/7. Pin an explicit constraint (^0.2 or 0.2.1 exactly) rather than relying on dev-master, otherwise a future force-push can break your build — and there is no newer tag to fall back to if it does.

  2. If a Ruwork\ReformBundle\RuworkReformBundle (or similarly named) bundle class is exposed, register it in config/bundles.php:

    Ruwork\ReformBundle\RuworkReformBundle::class => ['all' => true],
    

    If the package ships only loose classes instead of a bundle, skip this step and just use the namespaced classes directly.

  3. Skim the src/ tree first. In a package this small there is usually no docs site — the actual extension points live in the form type extensions and any ReformType / ReformExtension class. Read those before anything else.

First real use case: take a small DTO with a single property and build a form for it via FormFactoryInterface as you normally would, but swap the type you would have written (TextType, EntityType, etc.) for the Reform-provided equivalent. The payoff is supposed to be in typed mapping and consistent field configuration; verify that with a unit-test-style script on Symfony 4.1.x before wiring it into controllers. Doing this smoke test on the exact Symfony version you intend to run in production matters more than usual here, because the package's compatibility is pinned by patches like 0.2.1 rather than by a broad version range.

Implementation Patterns

Inject the form factory, not the container. In a controller or handler, take Symfony\Component\Form\FormFactoryInterface and build forms through it. Reform's value is in the type classes it provides — don't instantiate them manually.

public function __construct(private FormFactoryInterface $forms) {}

public function handle(Request $request, MyDto $dto): ?RedirectResponse
{
    $form = $this->forms->create(MyDtoType::class, $dto)->handleRequest($request);

    if ($form->isSubmitted() && $form->isValid()) {
        // persist $dto
        return $this->redirectToRoute('done');
    }

    return null;
}

Build reusable type classes around the DTO. Declare one AbstractType (or Reform equivalent) per DTO, configureOptions with data_class => MyDto::class, and compose Reform-provided child types. This is the workflow the package is aimed at — the day-to-day win is that each form type reads as a declarative mapping from DTO fields to widgets, with no procedural add() calls scattered in controllers.

Treat Reform types as drop-in children. They should slot into a standard FormBuilderInterface chain:

$builder
    ->add('email', ReformEmailType::class)
    ->add('name', ReformTextType::class, ['required' => false]);

If a Reform type does not accept the options you expect, fall back to the native Symfony type for that one field — mixing is fine because everything is still a FormTypeInterface.

Register form types as services. Tag them form.type and let autowiring resolve constructor dependencies (validator, repository, etc.). In services.yaml:

App\Form\:
    resource: '../src/Form/'
    tags: ['form.type']

Centralise translation of field labels and error messages. Reform reduces per-field configuration, so the remaining customisation typically moves into translation files under translations/validators.en.yaml and translations/messages.en.yaml. Keep labels keyed by <form>.<field> so the mapping stays predictable.

Test the form type, not the controller. Use TypeTestCase or a Symfony KernelTestCase with the form factory. Given the age of the package and the fact that compatibility is maintained by narrow point fixes, integration tests through the container are the only reliable way to catch BC breaks — unit tests against the raw classes are cheap and will survive.

Gotchas and Tips

  • This is an abandoned package. Zero dependents and a version line that stalled at 0.2.1 mean it was never adopted at scale. Budget time to read the source end-to-end; there is effectively no community knowledge base, no StackOverflow answers, and no maintained issue tracker.
  • Symfony version compatibility is the biggest risk — and 0.2.1 narrows it. The 0.2.1 release is a targeted fix "for Symfony 4.1.2", which tells you the maintainers were tracking a specific 4.1.x patch, not a range. Treat Symfony 4.1.x as the only realistically supported environment. Anything released in mid-2018 targets roughly Symfony 3.4–4.1; running it on Symfony 5/6/7 will likely fail because FormTypeInterface changed signatures (buildForm, configureOptions) and OptionsResolver behaviour tightened. Check the composer.json require block before you invest in it, and be aware that even a bump to a later 4.1.x point release is untested by the maintainers.
  • Bundle registration may or may not exist. Small Ruwork packages sometimes ship only classes and expect you to import the config yourself. If bin/console debug:container --tag=form.type shows nothing from the package, the bundle is not loaded and no types will be available.
  • data_class and empty data. Symfony forms bind null data by default when a DTO has not been initialised, and many small form helpers assume a hydrated object. Always instantiate the DTO (new MyDto()) in the controller before createForm, otherwise you will hit "Unable to transform" / TransformationFailedException at submit time.
  • Debugging mapping failures: drop into FormEvents::POST_SUBMIT with a listener that dumps $event->getForm()->getData(). This is faster than reading through form extensions when a field silently becomes null.
  • Do not extend Reform types if you can compose them. Inheritance across form types is fragile in Symfony (parent builders run first, options merge in unexpected ways), and with no maintained release you cannot rely on internal method stability. Compose via $builder->add(...) instead.
  • Pin the dependency and vendor it. Because the project is effectively unmaintained — with 0.2.1 being a compatibility patch rather than a feature release — commit the resolved version in composer.lock and consider a replace/provide shim if you later need to fork. Given the small surface area, forking to a local app/Reform/ namespace is often cheaper than fighting composer on a 2018-era 0.x package.
  • No asset or template output. Reform is a PHP form library; it will not provide Twig form themes. You will still write form_row() blocks yourself, and any custom widget will need its own block_<type>_widget in your Twig theme.
  • Extension points to look for: if the package exposes a FormTypeExtensionInterface, that is the cleanest place to add project-wide defaults (widget classes, required icons) without forking. Read src/Extension/ — if it is missing, you are probably expected to write your own AbstractTypeExtension.
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.
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
noith/settings
kda/laravel-package