wpdesk / wp-forms
WP Forms
Requires
- php: >=7.4 || ^8
- ext-curl: *
- ext-json: *
- wpdesk/wp-persistence: ^2.0|^3.0
- wpdesk/wp-view: ^2
Requires (Dev)
- 10up/wp_mock: *
- phpunit/phpunit: ^9
- wpdesk/phpstan-rules: ^1
- wpdesk/wp-code-sniffer: ^1.2.3
Suggests
None
Provides
None
Conflicts
None
Replaces
None
- dev-master
- 3.3.5
- 3.3.4
- 3.3.3
- 3.3.2
- 3.3.1
- 3.3.0
- 3.2.1
- 3.2.0
- 3.1.0
- 3.0.0
- 2.4.12
- 2.4.11
- 2.4.10
- 2.4.9
- 2.4.8
- 2.4.7
- 2.4.6
- 2.4.5
- 2.4.4
- 2.4.2
- 2.4.1
- 2.4.0
- 2.3.2
- 2.3.1
- 2.3
- 2.2.2
- 2.2.1
- 2.2.0
- 2.2.0-beta
- 2.1.0
- 2.1.0-beta
- 2.0.4
- 2.0.3
- 2.0.2
- 2.0.2-beta3
- 2.0.2-beta2
- 2.0.2-beta1
- 2.0.1
- 2.0
- 2.0-beta13
- 2.0-beta12
- 2.0-beta11
- 2.0-beta10
- 2.0-beta9
- 2.0-beta8
- 2.0-beta7
- 2.0-beta6
- 2.0-beta5
- 2.0-beta4
- 2.0-beta2
- 2.0-beta
- 1.0
- dev-feature/form-core
- dev-devel
- dev-feature/add-escaping-to-templates
- dev-feature/add-priority-sorting
This package is auto-updated.
Last update: 2026-08-30 13:48:15 UTC
README
Reusable form field objects, renderers and persistence helpers for WordPress projects.
wpdesk/wp-forms is a Composer package, not a standalone WordPress plugin. It is intended to be used from code that already runs inside WordPress, for example a plugin settings page or another admin form.
Requirements
- PHP
>=7.4 || ^8 - PHP extensions:
ext-curl,ext-json - Composer packages:
wpdesk/wp-persistence^2.0|^3.0,wpdesk/wp-view^2 - WordPress runtime for functions used by fields and templates, such as
sanitize_title(),sanitize_text_field(),sanitize_email(),wp_verify_nonce(),wp_editor()and escaping helpers - WooCommerce runtime only for templates and helpers that use WooCommerce functions, such as
wc_help_tip(),wc_get_product()and thewoocommerce_json_search_products_and_variationsAJAX action
Installation
Install the package as a runtime dependency:
composer require wpdesk/wp-forms
When working on this package itself, install development dependencies with:
composer install
Autoloading
Load Composer's autoloader in your plugin or application:
require_once __DIR__ . '/vendor/autoload.php';
The package uses the WPDesk\Forms\ PSR-4 namespace mapped to src/.
Basic Usage
Create field objects, pass them to FormWithFields, handle data submitted under the form ID and render the form with SimplePhpRenderer plus DefaultFormFieldResolver.
<?php use WPDesk\Forms\Field\CheckboxField; use WPDesk\Forms\Field\InputEmailField; use WPDesk\Forms\Field\SubmitField; use WPDesk\Forms\Form\FormWithFields; use WPDesk\Forms\Resolver\DefaultFormFieldResolver; use WPDesk\View\Renderer\SimplePhpRenderer; $fields = [ ( new InputEmailField() ) ->set_name( 'email' ) ->set_label( __( 'Email address', 'my-text-domain' ) ) ->set_required(), ( new CheckboxField() ) ->set_name( 'subscribe' ) ->set_label( __( 'Subscription', 'my-text-domain' ) ) ->set_sublabel( __( 'Subscribe to the mailing list', 'my-text-domain' ) ) ->set_default_value( CheckboxField::VALUE_FALSE ), ( new SubmitField() ) ->set_name( 'save' ) ->set_label( __( 'Save changes', 'my-text-domain' ) ) ->add_class( 'button-primary' ), ]; $form = new FormWithFields( $fields, 'newsletter_settings' ); $form->set_method( 'POST' ); $form->set_action( '' ); if ( isset( $_POST['newsletter_settings'] ) && is_array( $_POST['newsletter_settings'] ) ) { $form->handle_request( wp_unslash( $_POST['newsletter_settings'] ) ); if ( $form->is_valid() ) { $data = $form->get_data(); // Save $data in your persistence layer. } } $renderer = new SimplePhpRenderer( new DefaultFormFieldResolver() ); echo $form->render_form( $renderer );
Important behavior:
FormWithFieldsrenders request field names as{form_id}[{field_name}].handle_request()reads only fields declared in the form and sanitizes values with each field's sanitizer.is_valid()must be called before saving submitted data if validation matters.get_data()returns submitted or loaded values and fills missing fields with their default values.get_fields()sorts fields by ascending priority; the default priority is10.
Persistence
FormWithFields::set_data() can load values from a Psr\Container\ContainerInterface implementation.
FormWithFields::put_data() can write current form values to a WPDesk\Persistence\PersistentContainer, but it writes raw values only.
Use WPDesk\Forms\Persistence\FieldPersistenceStrategy when fields with serializers are involved, because it calls field serializers during save and load.
use WPDesk\Forms\Persistence\FieldPersistenceStrategy; $strategy = new FieldPersistenceStrategy( $persistent_container ); if ( isset( $_POST[ $form->get_form_id() ] ) && is_array( $_POST[ $form->get_form_id() ] ) ) { $form->handle_request( wp_unslash( $_POST[ $form->get_form_id() ] ) ); if ( $form->is_valid() ) { $strategy->persist_fields( $form, $form->get_data() ); } } $loaded_data = $strategy->load_fields( $form ); // Pass $loaded_data to your own field owner, container adapter or view layer.
Rendering Fields as Data
Use WPDesk\Forms\Renderer\JsonNormalizedRenderer to convert fields to normalized arrays for custom frontends or JavaScript-driven UIs.
use WPDesk\Forms\Renderer\JsonNormalizedRenderer; $renderer = new JsonNormalizedRenderer(); $fields_data = $renderer->render_fields( $form, $form->get_data(), $form->get_form_id() );
Available Fields
Text and input fields:
InputTextFieldInputEmailFieldInputNumberFieldHiddenFieldTextAreaFieldMultipleInputTextFieldDateFieldDatePickerFieldTimepickerFieldImageInputFieldWPEditorField
Choice fields:
CheckboxFieldToggleFieldRadioFieldSelectFieldProductSelectWooSelect
Layout and action fields:
HeaderParagraphButtonFieldSubmitFieldNoOnceField, which renders and validates a WordPress nonce field
Base classes:
BasicFieldprovides common fluent setters such asset_name(),set_label(),set_description(),set_description_tip(),set_placeholder(),set_default_value(),set_required(),set_priority(),add_class()andadd_data().NoValueFieldis the base class for display/action fields that normally do not process a submitted value.
Deprecated field:
WyswigFieldis deprecated; useWPEditorFieldinstead.
Template notes:
DefaultFormFieldResolverresolves templates from the packagetemplates/directory.ProductSelectdepends on WooCommerce product lookup functions and admin AJAX behavior.WooSelectreturns thewoo-selecttemplate name andTimepickerFieldreturns thetimepickertemplate name. Matching templates are not bundled in this package, so provide them through your renderer/resolver setup before using these fields with the default renderer.
Validators, Sanitizers and Serializers
Validators:
ChainValidatorNoValidateValidatorNonceValidatorRequiredValidator, attached automatically byBasicField::set_required()
Sanitizers:
NoSanitize, the default sanitizer inBasicFieldTextFieldSanitizer, used by text-like fieldsEmailSanitizer, used byInputEmailFieldCallableSanitizer, for custom sanitizer callbacks
Serializers:
JsonSerializerProductSelectSerializerSerializeSerializer
Fields that return true from has_serializer() should be persisted through FieldPersistenceStrategy if you want serializer-aware save/load behavior.
Development
Available Composer scripts:
composer phpcs composer phpstan composer phpcbf composer phpunit-unit composer phpunit-unit-fast composer phpunit-integration composer phpunit-integration-fast
License
This package is released under the MIT license.