PHPackages                             jooservices/form-builder - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Validation &amp; Sanitization](/categories/validation)
4. /
5. jooservices/form-builder

ActiveLibrary[Validation &amp; Sanitization](/categories/validation)

jooservices/form-builder
========================

Standalone PHP 8.5+ schema-driven form builder with DTO-backed form definitions, HTML rendering, validation, normalization, and repeater support.

v1.0.0(3w ago)079[4 PRs](https://github.com/jooservices/form-builder/pulls)MITPHPPHP &gt;=8.5CI passing

Since May 18Pushed 2d agoCompare

[ Source](https://github.com/jooservices/form-builder)[ Packagist](https://packagist.org/packages/jooservices/form-builder)[ RSS](/packages/jooservices-form-builder/feed)WikiDiscussions develop Synced 1w ago

READMEChangelog (1)Dependencies (12)Versions (4)Used By (0)

JOOservices Form Builder
========================

[](#jooservices-form-builder)

[![CI](https://github.com/jooservices/form-builder/actions/workflows/ci.yml/badge.svg)](https://github.com/jooservices/form-builder/actions/workflows/ci.yml)[![PHP Version](https://camo.githubusercontent.com/36b923864f3d5c2cd2af63b7f31d4c9458f3d62a66ecab2c9f747b7981009026/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068702d253345253344382e352d3737376262342e737667)](https://php.net)[![License](https://camo.githubusercontent.com/8bb50fd2278f18fc326bf71f6e88ca8f884f72f179d3e555e20ed30157190d0d/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d677265656e2e737667)](LICENSE)[![Packagist Version](https://camo.githubusercontent.com/d9aeea46f7fadfe83d2e0f94e8836ce5cc3f0aad5af201b705064c85a5200475/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f6a6f6f73657276696365732f666f726d2d6275696c6465722e737667)](https://packagist.org/packages/jooservices/form-builder)[![Codecov](https://camo.githubusercontent.com/7e9740445f6a1d9199cdf2cc9db6e42a4521af81c575dacfb98fcca0c5c1c70f/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636f762f632f6769746875622f6a6f6f73657276696365732f666f726d2d6275696c6465722e737667)](https://codecov.io/gh/jooservices/form-builder)[![OpenSSF Scorecard](https://camo.githubusercontent.com/14c6f821198db823f8b1f74695b60351333715a687d3cba474019997e1ee5651/68747470733a2f2f6170692e73636f7265636172642e6465762f70726f6a656374732f6769746875622e636f6d2f6a6f6f73657276696365732f666f726d2d6275696c6465722f6261646765)](https://scorecard.dev/viewer/?uri=github.com/jooservices/form-builder)

`jooservices/form-builder` is a standalone PHP 8.5+ schema-driven form builder for JSON-defined forms. It parses form schemas, validates schema shape, renders semantic HTML, returns renderless config arrays, exposes asset manifests or safe asset tags, validates submitted values, normalizes submitted values, and supports repeaters, rich-text editor metadata, media input metadata, and generic file input metadata without coupling to Laravel, WordPress, Joomla, Symfony upload objects, PSR-7 uploads, or storage frameworks.

Install
-------

[](#install)

```
composer require jooservices/form-builder
```

Quick Start
-----------

[](#quick-start)

```
use JOOservices\FormBuilder\FormBuilder;

$builder = FormBuilder::fromJson($json);

$schema = $builder->validateSchema();
$html = $builder->renderHtml([
    'values' => $existingValues,
    'errors' => $errors,
]);

$config = $builder->toConfigArray();

$assets = $builder->assets();
$assetTags = $builder->renderAssetTags();

$submission = $builder->validateSubmission($input);

if ($submission->passes()) {
    $values = $submission->normalizedValues();
}
```

JSON Schema Example
-------------------

[](#json-schema-example)

```
{
  "key": "default_story_form",
  "name": "Default Story Form",
  "version": "1.0.0",
  "method": "post",
  "fields": [
    {
      "key": "title",
      "type": "text",
      "label": "Title",
      "required": true,
      "placeholder": "Story title",
      "maxlength": 255
    },
    {
      "key": "intro",
      "type": "editor",
      "label": "Intro",
      "required": true,
      "html": true,
      "editor": {
        "provider": "tinymce",
        "profile": "basic_html"
      }
    },
    {
      "key": "chapters",
      "type": "repeater",
      "label": "Chapters",
      "required": true,
      "min_items": 1,
      "default_items": 1,
      "fields": [
        {
          "key": "title",
          "type": "text",
          "label": "Chapter Title",
          "required": true
        },
        {
          "key": "media",
          "type": "media",
          "label": "Chapter Media",
          "accept": ["image/*"],
          "drag_drop": true,
          "preview": true
        },
        {
          "key": "attachment",
          "type": "file",
          "label": "Chapter Attachment",
          "accept": [".pdf", ".docx", "application/pdf"],
          "max_files": 1,
          "max_size_mb": 20
        },
        {
          "key": "content",
          "type": "editor",
          "label": "Chapter Content",
          "required": true,
          "html": true
        }
      ]
    }
  ]
}
```

Render HTML
-----------

[](#render-html)

Editor fields render as safe `` fallbacks with `data-form-editor`, `data-form-editor-profile`, and `data-form-editor-config`. Media fields render as standard `` controls with optional drag/drop and preview containers driven by data attributes. File fields render as standard `` controls with `data-form-file`, `data-form-file-accept`, `data-form-file-max-files`, and `data-form-file-max-size-mb` metadata, including repeater-safe names such as `chapters[0][documents][]`.

Render Config
-------------

[](#render-config)

`toConfigArray()` returns a renderless structure for Blade, Vue, React, CLI previews, or custom UI adapters. Repeater items, editor metadata, media metadata, and file metadata are preserved in the config output.

Assets
------

[](#assets)

Use the asset facade when the consuming application needs standalone CSS/JS metadata without framework coupling:

```
$builder = FormBuilder::fromJson($json);

$manifest = $builder->assets([
  'tinymce_url' => 'https://cdn.tiny.cloud/1/no-api-key/tinymce/7/tinymce.min.js',
]);

echo $builder->renderAssetTags();
```

The manifest exposes `css`, `js`, `inline_css`, `inline_js`, `features`, and `providers`. TinyMCE is opt-in by schema usage and can be disabled or overridden:

```
$manifest = $builder->assets([
  'load_tinymce' => false,
  'package_asset_mode' => 'url',
  'package_asset_base_url' => 'https://static.example.com/form-builder',
]);
```

If `package_asset_mode` is set to `url` without a usable `package_asset_base_url`, package helper assets are omitted instead of silently falling back to inline output.

Use `renderAssetTags()` for simple PHP apps. In WordPress Management or any host application, prefer reading the manifest and enqueueing or serving those assets in the application layer.

File Versus Media
-----------------

[](#file-versus-media)

- `media` is for media-picker style UX such as image, video, preview, or dropzone flows.
- `file` is for generic upload inputs such as PDF, DOCX, CSV, or ZIP.
- Both stay at schema, HTML, config, validation, and normalization level only.
- Neither field moves, stores, or validates uploaded bytes.

Validate Submission
-------------------

[](#validate-submission)

Submission validation returns structured `ValidationErrorData` objects with `path`, `message`, `code`, and `context`. Repeater paths follow dot notation such as `chapters.0.title`. File and media validation accept metadata-style values, scalar references, or lists according to field shape, but they do not depend on framework upload classes.

Repeater Behavior
-----------------

[](#repeater-behavior)

- Repeater item names render as `chapters[0][title]` and `chapters[0][media][]` for multiple media.
- Default repeater items render when no runtime values exist.
- Submitted order is preserved.

Custom Fields
-------------

[](#custom-fields)

Register a custom field adapter when you need application-specific field behavior:

```
$builder->registerFieldAdapter($adapter);
```

Or use the convenience registration API when you already have custom renderer, validator, and normalizer objects:

```
$builder->registerFieldType('media_picker', $renderer, $validator, $normalizer);
```

Security Notes
--------------

[](#security-notes)

- Labels, placeholders, text values, and attributes are escaped.
- Event handler attributes like `onclick` are filtered from rendered attributes.
- Editor content is preserved safely inside `` output.
- This package does not sanitize rich HTML content by default.
- This package does not inspect file contents, read upload bytes, or store uploaded files.
- Consuming applications must validate real uploads, MIME policy, file size, and storage server-side.
- Asset tags escape URLs and attributes, but host applications still control CSP, CDN policy, and static file serving.

What This Package Does Not Do
-----------------------------

[](#what-this-package-does-not-do)

- It does not save posts, pages, or database records.
- It does not perform WordPress, Joomla, or Laravel integration.
- It does not bundle TinyMCE, CKEditor, TipTap, Quill, or uploader libraries into PHP source.
- It does not move or store uploaded files.
- It does not call `wp_enqueue_script`, service providers, route registries, or framework lifecycle hooks.
- It does not provide AI content generation.

WordPress Management Guidance
-----------------------------

[](#wordpress-management-guidance)

- Store schemas in WordPress Management configuration or database layers.
- Use `FormBuilder` to validate schema, render HTML or config, and validate or normalize submitted values.
- Read `assets()` and enqueue or serve the returned manifest through WordPress Management, not inside this package.
- Handle actual upload transport, storage, attachment creation, and security policy inside WordPress Management.

Docs And AI Guidance
--------------------

[](#docs-and-ai-guidance)

- [Documentation](docs/README.md)
- [AGENTS.md](AGENTS.md)
- [CLAUDE.md](CLAUDE.md)
- [AI Skills](ai/skills/README.md)

###  Health Score

45

—

FairBetter than 91% of packages

Maintenance97

Actively maintained with recent releases

Popularity13

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 70.6% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

22d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/142772948?v=4)[JOOservices Ltd](/maintainers/jooservices)[@jooservices](https://github.com/jooservices)

---

Top Contributors

[![soulevilx](https://avatars.githubusercontent.com/u/2688707?v=4)](https://github.com/soulevilx "soulevilx (24 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (10 commits)")

---

Tags

composer-packageform-builderformshtml-rendererjooservicesjson-schemaphpphp85schema-drivenvalidationphpschemavalidationjson-schemadata-transfer-objectdtoFormsform-builderphp85dynamic formshtml formsJOOservicesstandalone-libraryrepeater-fields

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/jooservices-form-builder/health.svg)

```
[![Health](https://phpackages.com/badges/jooservices-form-builder/health.svg)](https://phpackages.com/packages/jooservices-form-builder)
```

###  Alternatives

[opis/json-schema

Json Schema Validator for PHP

64841.2M257](/packages/opis-json-schema)[yorcreative/laravel-argonaut-dto

Argonaut is a lightweight Data Transfer Object (DTO) package for Laravel that supports nested casting, recursive serialization, and validation out of the box. Ideal for service layers, APIs, and clean architecture workflows.

1063.3k2](/packages/yorcreative-laravel-argonaut-dto)[evaisse/php-json-schema-generator

A JSON Schema Generator.

20310.5k1](/packages/evaisse-php-json-schema-generator)[friendsofhyperf/validated-dto

The Data Transfer Objects with validation for Hyperf.

1514.2k](/packages/friendsofhyperf-validated-dto)[fab2s/dt0

Immutable DTOs with bidirectional casting. No framework required. 8x faster than the alternative.

101.9k1](/packages/fab2s-dt0)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
