Fields
How to define and configure every field type in Perique Settings Page.
Every field is created from within the fields() method on your Abstract_Settings subclass. Push instances into the Setting_Collection:
use PinkCrab\Perique_Settings_Page\Setting\Abstract_Settings;
use PinkCrab\Perique_Settings_Page\Setting\Setting_Collection;
use PinkCrab\Perique_Settings_Page\Setting\Field\{ Text, Number, Select };
class My_Settings extends Abstract_Settings {
protected function is_grouped(): bool {
return true;
}
public function group_key(): string {
return 'my_settings';
}
protected function fields( Setting_Collection $settings ): Setting_Collection {
return $settings->push(
Text::new( 'site_name' )->set_label( 'Site Name' )->set_required(),
Number::new( 'limit' )->set_label( 'Limit' )->set_min( 1 )->set_max( 100 )
);
}
}
Every field uses a ::new( 'key' ) static constructor. All setters return static for fluent chaining.
Each section below shows a single comprehensive example with inline comments — chain only the methods you need; none are required beyond set_label().
Common methods
Available on every field.
| Method | Purpose |
|---|---|
set_label( string ) | Visible label above the input. |
set_description( string ) | Help text below the input. |
set_value( mixed ) | Default / stored value (normally set by the hydration layer, not by you). |
set_required( bool = true ) | Blocks submission when empty. |
set_read_only( bool = true ) | Renders as read-only. |
set_id( string ) | Override the auto-generated HTML id. |
add_class( string ) | Append a CSS class (call repeatedly to add more). |
set_icon( string ) | Icon URL or dashicon class. |
set_label_position( string ) / label_before() / label_after() | Position the label above (default) or below the input. |
set_before( string ) / set_after( string ) | HTML rendered inside the wrapper before / after the input. |
set_attribute( string, mixed ) | Arbitrary HTML attribute. |
set_flag( string ) | Arbitrary HTML boolean flag (e.g. autofocus). |
set_sanitize( callable ) | Override the per-field default sanitiser. |
set_validate( callable \| Validator ) | Server-side validation — any callable returning truthy/falsy, or a Respect\Validation\Validator. |
set_config( callable ) | Escape hatch. Receives the final Form Component element at render time. |
clone_as( string ) | Clone the field definition under a different key. |
Shared traits
Trait methods appear on the fields that include them. Each field section below lists its traits.
| Trait | Methods | Used by |
|---|---|---|
Placeholder | set_placeholder( string ) | Text, Email, Phone, Url, Password, Textarea, Number, WP_Editor, User_Picker, Post_Picker |
Data | set_data( string key, string value ) | Almost every field |
Pattern | set_pattern( string regex ) | Text, Email, Phone, Url |
Options | set_option( string value, string label, string group = '' ) | Text (datalist), Number (datalist), Select, Radio, Checkbox_Group |
Range | set_min( mixed ), set_max( mixed ), set_step( mixed ) | Number |
Disabled | set_disabled( bool = true ) | Checkbox, Checkbox_Group, Radio, User_Picker, Post_Picker, Repeater |
Multiple | set_multiple( bool = true ) | Select, User_Picker, Post_Picker |
Autocomplete | set_autocomplete( string ) | Colour |
Checked_Value | set_checked_value( string ) | Checkbox, Checkbox_Group |
Query | set_query_args( array ), set_option_label( callable ) | Post_Picker |
Text inputs
Text
Setting\Field\Text — <input type="text">. Default sanitiser: sanitize_text_field.
Traits: Placeholder, Data, Pattern, Options (rendered as a <datalist> of suggestions).
use Respect\Validation\Validator as v;
Text::new( 'company_name' )
// Visible label above the input.
->set_label( 'Company Name' )
// Greyed-out hint shown while the field is empty.
->set_placeholder( 'Acme Ltd.' )
// Help text rendered below the input.
->set_description( 'Registered company name as it appears on Companies House.' )
// Blocks submission if the field is empty.
->set_required()
// Renders the input as read-only (value still submitted).
->set_read_only()
// Override the auto-generated HTML id.
->set_id( 'acme-company' )
// Append one or more CSS classes to the input element.
->add_class( 'is-highlight' )
// data-* attributes for JS hooks.
->set_data( 'validate', 'alphanumeric' )
// HTML5 pattern attribute for client-side validation.
->set_pattern( '[A-Za-z0-9 \-&]+' )
// Datalist suggestions (from the Options trait).
->set_option( 'acme', 'Acme Ltd.' )
->set_option( 'globex', 'Globex Corp.' )
// HTML rendered inside the wrapper before / after the input.
->set_before( '<span class="prefix">Co:</span>' )
->set_after( '<small>Must match Companies House records.</small>' )
// Arbitrary HTML attributes.
->set_attribute( 'autocomplete', 'organization' )
// Boolean flag rendered as a bare HTML attribute.
->set_flag( 'autofocus' )
// Override the default sanitiser (sanitize_text_field).
->set_sanitize( fn( $v ) => trim( (string) $v ) )
// Server-side validation — callable or Respect\Validation\Validator.
->set_validate( v::stringType()->length( 1, 100 ) );
Setting\Field\Email — <input type="email">. Default sanitiser: sanitize_email.
Traits: Placeholder, Data, Pattern.
use Respect\Validation\Validator as v;
Email::new( 'support_email' )
// Visible label above the input.
->set_label( 'Support Email' )
// Greyed-out hint shown while the field is empty.
->set_placeholder( 'help@example.com' )
// Help text rendered below the input.
->set_description( 'Shown to customers in the site footer.' )
// Blocks submission if the field is empty.
->set_required()
// Override the auto-generated HTML id.
->set_id( 'acme-support-email' )
// Append a CSS class.
->add_class( 'is-contact' )
// data-* attributes for JS hooks.
->set_data( 'section', 'contact' )
// HTML5 pattern attribute (runs before browser email validation).
->set_pattern( '.+@.+\..+' )
// HTML rendered inside the wrapper before / after the input.
->set_after( '<small>This address receives every contact-form submission.</small>' )
// Arbitrary HTML attributes.
->set_attribute( 'autocomplete', 'email' )
// Override the default sanitiser (sanitize_email) with a WordPress callable.
->set_sanitize( 'sanitize_email' )
// Server-side validation — a built-in WordPress function by name.
->set_validate( 'is_email' );
Phone
Setting\Field\Phone — <input type="tel">. Default sanitiser: sanitize_text_field.
Traits: Placeholder, Data, Pattern.
use Respect\Validation\Validator as v;
Phone::new( 'support_phone' )
// Visible label above the input.
->set_label( 'Support Phone' )
// Greyed-out hint shown while the field is empty.
->set_placeholder( '+44 7700 900000' )
// Help text rendered below the input.
->set_description( 'Include the international dialling code.' )
// Blocks submission if the field is empty.
->set_required()
// Override the auto-generated HTML id.
->set_id( 'acme-support-phone' )
// Append a CSS class.
->add_class( 'is-contact' )
// data-* attributes for JS hooks.
->set_data( 'format', 'international' )
// HTML5 pattern — digits, spaces and an optional leading +.
->set_pattern( '\+?[0-9\s]+' )
// HTML rendered after the input.
->set_after( '<small>Office hours: Mon–Fri 9:00–17:00 GMT.</small>' )
// Arbitrary HTML attributes.
->set_attribute( 'autocomplete', 'tel' )
// Override the default sanitiser.
->set_sanitize( fn( $v ) => preg_replace( '/\s+/', ' ', trim( (string) $v ) ) )
// Server-side validation — plain callable.
->set_validate( fn( $v ) => (bool) preg_match( '/^\+?[0-9\s]{7,}$/', (string) $v ) );
Url
Setting\Field\Url — <input type="url">. Default sanitiser: esc_url_raw.
Traits: Placeholder, Data, Pattern.
Url::new( 'website' )
// Visible label above the input.
->set_label( 'Website' )
// Greyed-out hint shown while the field is empty.
->set_placeholder( 'https://example.com' )
// Help text rendered below the input.
->set_description( 'Must start with https:// or http://.' )
// Blocks submission if the field is empty.
->set_required()
// Override the auto-generated HTML id.
->set_id( 'acme-website' )
// Append a CSS class.
->add_class( 'is-wide' )
// data-* attributes for JS hooks.
->set_data( 'scheme', 'https-preferred' )
// HTML5 pattern — only allow https://.
->set_pattern( 'https://.+' )
// HTML rendered after the input.
->set_after( '<small>Linked from the footer.</small>' )
// Arbitrary HTML attributes.
->set_attribute( 'autocomplete', 'url' )
// Override the default sanitiser (esc_url_raw) with a closure.
->set_sanitize( fn( $e ) => esc_url_raw( trim( (string) $e ) ) )
// Server-side validation — plain closure using filter_var.
->set_validate( fn( $e ) => false !== filter_var( $e, FILTER_VALIDATE_URL ) );
Password
Setting\Field\Password — <input type="password">. Default sanitiser: sanitize_text_field.
Traits: Placeholder, Data.
use Respect\Validation\Validator as v;
Password::new( 'api_secret' )
// Visible label above the input.
->set_label( 'API Secret' )
// Greyed-out hint shown while the field is empty.
->set_placeholder( 'sk_live_…' )
// Help text rendered below the input.
->set_description( 'Paste the secret key from your dashboard.' )
// Blocks submission if the field is empty.
->set_required()
// Renders the input as read-only (value still submitted).
->set_read_only()
// Override the auto-generated HTML id.
->set_id( 'acme-api-secret' )
// Append one or more CSS classes.
->add_class( 'is-sensitive' )
->add_class( 'wide' )
// data-* attributes for JS hooks.
->set_data( 'min-length', '32' )
->set_data( 'reveal-toggle', 'true' )
// HTML rendered inside the wrapper before / after the input.
->set_before( '<span class="prefix">sk_</span>' )
->set_after( '<a href="https://example.com/keys" target="_blank">Find your key</a>' )
// Arbitrary HTML attributes.
->set_attribute( 'autocomplete', 'new-password' )
// Boolean flag rendered as a bare HTML attribute.
->set_flag( 'autofocus' )
// Override the default sanitiser (sanitize_text_field).
->set_sanitize( fn( $v ) => trim( (string) $v ) )
// Server-side validation — callable or Respect\Validation\Validator.
->set_validate( v::stringType()->length( 32, null ) );
Textarea
Setting\Field\Textarea — multi-line text. Default sanitiser: sanitize_textarea_field.
Traits: Placeholder, Data.
Textarea::new( 'bio' )
// Visible label above the input.
->set_label( 'Biography' )
// Greyed-out hint shown while the field is empty.
->set_placeholder( 'Tell us about yourself...' )
// Help text rendered below the input.
->set_description( 'Plain text only. Shown on the team page.' )
// Blocks submission if the field is empty.
->set_required()
// Visible row / column counts.
->set_rows( 8 )
->set_cols( 60 )
// Override the auto-generated HTML id.
->set_id( 'acme-bio' )
// Append a CSS class.
->add_class( 'is-wide' )
// data-* attributes for JS hooks.
->set_data( 'max-words', '250' )
// HTML rendered after the input.
->set_after( '<small>Maximum 250 words.</small>' )
// Arbitrary HTML attributes.
->set_attribute( 'spellcheck', 'true' )
// Override the default sanitiser (sanitize_textarea_field) with a string callable.
->set_sanitize( 'sanitize_textarea_field' )
// Server-side validation — plain closure capping length.
->set_validate( fn( $e ) => strlen( (string) $e ) <= 2000 );
Field-specific methods:
| Method | Purpose |
|---|---|
set_rows( int ) | Visible row count. |
set_cols( int ) | Visible column count. |
Hidden
Setting\Field\Hidden — <input type="hidden">. Default sanitiser: sanitize_text_field.
No traits. Use when you need to carry a value alongside the editable fields (a token, a schema version, a reference ID).
Hidden::new( 'form_version' )
// The stored value.
->set_value( 'v2' )
// Override the auto-generated HTML id.
->set_id( 'acme-form-version' )
// Append a CSS class (typically unused on hidden fields).
->add_class( 'acme-hidden' )
// data-* attributes for JS hooks.
->set_data( 'purpose', 'version-token' )
// Arbitrary HTML attributes.
->set_attribute( 'autocomplete', 'off' )
// Override the default sanitiser.
->set_sanitize( fn( $v ) => trim( (string) $v ) );
Number
Number
Setting\Field\Number — <input type="number">. Default sanitiser casts to int when decimal_places ≤ 1, otherwise rounds the float to the configured precision.
Traits: Placeholder, Data, Range, Options (datalist suggestions).
Number::new( 'price' )
// Visible label above the input.
->set_label( 'Price (GBP)' )
// Greyed-out hint shown while the field is empty.
->set_placeholder( '9.99' )
// Help text rendered below the input.
->set_description( 'Excludes VAT.' )
// Blocks submission if the field is empty.
->set_required()
// Range constraints (from the Range trait).
->set_min( 0 )
->set_max( 10000 )
->set_step( 0.01 )
// Number of decimal places — 0–1 stores as int, higher rounds a float.
->set_decimal_places( 2 )
// Override the auto-generated HTML id.
->set_id( 'acme-price' )
// Append a CSS class.
->add_class( 'is-monetary' )
// data-* attributes for JS hooks.
->set_data( 'currency', 'GBP' )
// Datalist suggestions (from the Options trait).
->set_option( '9.99', 'Starter' )
->set_option( '19.99', 'Pro' )
// HTML rendered inside the wrapper before / after the input.
->set_before( '<span class="prefix">£</span>' )
->set_after( '<small>Excl. VAT.</small>' )
// Arbitrary HTML attributes.
->set_attribute( 'inputmode', 'decimal' )
// Override the default sanitiser.
->set_sanitize( fn( $e ) => round( (float) $e, 2 ) )
// Server-side validation — WordPress/PHP built-in by name.
->set_validate( 'is_numeric' );
Field-specific methods:
| Method | Purpose |
|---|---|
set_decimal_places( int ) | 0–1 stores as int; higher values round a float to that precision. |
Selection
Select
Setting\Field\Select — <select> dropdown, single or multiple. Default sanitiser handles both scalar and array values.
Traits: Multiple, Data, Options.
Select::new( 'role' )
// Visible label above the input.
->set_label( 'Role' )
// Help text rendered below the input.
->set_description( 'Controls which admin screens this user can access.' )
// Blocks submission if nothing is selected.
->set_required()
// Allow multiple selections (value becomes an array).
->set_multiple()
// Options. The third argument creates / reuses an <optgroup>.
->set_option( 'admin', 'Administrator', 'Staff' )
->set_option( 'editor', 'Editor', 'Staff' )
->set_option( 'author', 'Author', 'Contributors' )
// Override the auto-generated HTML id.
->set_id( 'acme-role' )
// Append a CSS class.
->add_class( 'is-role-picker' )
// data-* attributes for JS hooks.
->set_data( 'default', 'editor' )
// HTML rendered after the input.
->set_after( '<small>Hold Ctrl/Cmd to select multiple.</small>' )
// Arbitrary HTML attributes.
->set_attribute( 'size', '5' )
// Override the default sanitiser.
->set_sanitize( fn( $e ) => is_array( $e ) ? array_map( 'sanitize_key', $e ) : sanitize_key( (string) $e ) )
// Server-side validation — closure covering both scalar and array values.
->set_validate(
fn( $e ) => is_array( $e )
? array_diff( $e, array( 'admin', 'editor', 'author' ) ) === array()
: in_array( $e, array( 'admin', 'editor', 'author' ), true )
);
Radio
Setting\Field\Radio — single-choice radio group.
Traits: Disabled, Data, Options.
use Respect\Validation\Validator as v;
Radio::new( 'plan' )
// Visible label above the group.
->set_label( 'Plan' )
// Help text rendered below the group.
->set_description( 'Choose one.' )
// Blocks submission if nothing is selected.
->set_required()
// Options.
->set_option( 'free', 'Free' )
->set_option( 'pro', 'Pro' )
->set_option( 'enterprise', 'Enterprise' )
// Default value.
->set_value( 'free' )
// Disable the whole group.
->set_disabled( false )
// Override the auto-generated HTML id.
->set_id( 'acme-plan' )
// Append a CSS class.
->add_class( 'is-plan-picker' )
// data-* attributes for JS hooks.
->set_data( 'default', 'free' )
// HTML rendered after the group.
->set_after( '<small>Upgrade any time.</small>' )
// Server-side validation.
->set_validate( v::in( array( 'free', 'pro', 'enterprise' ) ) );
Checkbox
Setting\Field\Checkbox — single on/off checkbox.
Traits: Disabled, Data, Checked_Value.
Checkbox::new( 'newsletter' )
// Visible label beside the checkbox.
->set_label( 'Subscribe to newsletter' )
// Help text rendered below the checkbox.
->set_description( 'We send one email per month — unsubscribe any time.' )
// Render the label after the input (default is before).
->label_after()
// Value stored when checked (default is 'on').
->set_checked_value( 'subscribed' )
// Default state.
->set_value( 'subscribed' )
// Disable the checkbox.
->set_disabled( false )
// Override the auto-generated HTML id.
->set_id( 'acme-newsletter' )
// Append a CSS class.
->add_class( 'is-optin' )
// data-* attributes for JS hooks.
->set_data( 'consent', 'marketing' )
// Server-side validation — accept the checked value or an empty string.
->set_validate( fn( $v ) => in_array( $v, array( '', 'subscribed' ), true ) );
Checkbox_Group
Setting\Field\Checkbox_Group — multiple checkboxes sharing one key. Stored as an array.
Traits: Disabled, Data, Options, Checked_Value.
Checkbox_Group::new( 'features' )
// Visible label above the group.
->set_label( 'Enabled Features' )
// Help text rendered below the group.
->set_description( 'Tick any the plugin should activate on boot.' )
// Options.
->set_option( 'search', 'Full-text search' )
->set_option( 'api', 'Public API' )
->set_option( 'webhooks', 'Webhooks' )
// Value stored for each checked item (default is 'on').
->set_checked_value( '1' )
// Default checked items.
->set_value( array( 'search' ) )
// Disable the group.
->set_disabled( false )
// Override the auto-generated HTML id.
->set_id( 'acme-features' )
// Append a CSS class.
->add_class( 'is-feature-list' )
// data-* attributes for JS hooks.
->set_data( 'section', 'features' )
// Server-side validation — only allow known option keys.
->set_validate(
fn( $v ) => is_array( $v )
&& array_diff( $v, array( 'search', 'api', 'webhooks' ) ) === array()
);
Specialised
Colour
Setting\Field\Colour — HTML5 <input type="color">. Default sanitiser: sanitize_text_field.
Traits: Data, Autocomplete.
use Respect\Validation\Validator as v;
Colour::new( 'brand_colour' )
// Visible label above the input.
->set_label( 'Brand Colour' )
// Help text rendered below the input.
->set_description( 'Used for buttons and links in the theme.' )
// Default colour (hex).
->set_value( '#3858e9' )
// Required on submit.
->set_required()
// Override the auto-generated HTML id.
->set_id( 'acme-brand-colour' )
// Append a CSS class.
->add_class( 'is-brand' )
// data-* attributes for JS hooks.
->set_data( 'token', 'brand-primary' )
// Disable browser autofill (from the Autocomplete trait).
->set_autocomplete( 'off' )
// HTML rendered after the input.
->set_after( '<small>Stored as a hex code.</small>' )
// Override the default sanitiser — accept only #rrggbb.
->set_sanitize( fn( $v ) => sanitize_hex_color( (string) $v ) ?: '#000000' )
// Server-side validation — must be a hex colour.
->set_validate( v::regex( '/^#[0-9a-f]{6}$/i' ) );
Media_Library
Setting\Field\Media_Library — opens the WordPress Media Library modal and stores the selected attachment’s ID.
No traits. Read the value back with wp_get_attachment_image() / wp_get_attachment_url().
use Respect\Validation\Validator as v;
Media_Library::new( 'logo' )
// Visible label above the picker.
->set_label( 'Site Logo' )
// Help text rendered below the picker.
->set_description( 'Recommended size: 512×512. PNG with transparency preferred.' )
// Required on submit.
->set_required()
// Override the auto-generated HTML id.
->set_id( 'acme-logo' )
// Append a CSS class.
->add_class( 'is-branding' )
// data-* attributes for JS hooks.
->set_data( 'mime', 'image' )
// HTML rendered after the picker.
->set_after( '<small>Stored as the attachment ID — render with wp_get_attachment_image().</small>' )
// Server-side validation — must resolve to a real attachment.
->set_validate( fn( $v ) => (bool) wp_get_attachment_url( (int) $v ) );
WP_Editor
Setting\Field\WP_Editor — full wp_editor() instance (TinyMCE + Quicktags). Default sanitiser: wp_kses_post.
Traits: Placeholder.
WP_Editor::new( 'about' )
// Visible label above the editor.
->set_label( 'About' )
// Greyed-out hint shown while the field is empty.
->set_placeholder( 'Tell visitors about your site...' )
// Help text rendered below the editor.
->set_description( 'Rich text. Shown on the About page.' )
// Required on submit.
->set_required()
// Options forwarded to wp_editor() — see _WP_Editors::parse_settings().
->set_options( array(
'media_buttons' => true,
'textarea_rows' => 12,
'teeny' => false,
'tinymce' => array(
'toolbar1' => 'bold italic underline | bullist numlist | link unlink | undo redo',
),
) )
// Override the auto-generated HTML id (used as the editor id too).
->set_id( 'acme-about' )
// Append a CSS class to the wrapper.
->add_class( 'is-wysiwyg' )
// data-* attributes for JS hooks.
->set_data( 'section', 'about' )
// HTML rendered after the editor.
->set_after( '<small>HTML allowed — sanitised through wp_kses_post.</small>' )
// Override the default sanitiser (wp_kses_post).
->set_sanitize( fn( $v ) => wp_kses_post( (string) $v ) );
Field-specific methods:
| Method | Purpose |
|---|---|
set_options( array ) | Options forwarded to wp_editor() — see _WP_Editors::parse_settings(). |
User_Picker
Setting\Field\User_Picker — type-ahead search-and-pick for WordPress users. The picker calls a bundled REST endpoint as the user types and stores the selected user’s ID.
Traits: Multiple, Data, Disabled, Placeholder.
User_Picker::new( 'site_owner' )
// Visible label above the picker.
->set_label( 'Site Owner' )
// Greyed-out hint shown inside the empty search box.
->set_placeholder( 'Search users...' )
// Help text rendered below the picker.
->set_description( 'Contact details shown in the footer.' )
// Required on submit.
->set_required()
// Allow multiple users (value becomes an array of IDs).
->set_multiple()
// Restrict the search to a single role slug.
->set_role( 'administrator' )
// Disable the picker.
->set_disabled( false )
// Override the auto-generated HTML id.
->set_id( 'acme-owner' )
// Append a CSS class.
->add_class( 'is-owner-picker' )
// data-* attributes for JS hooks.
->set_data( 'min-search', '2' )
// Override the label shown for each matched user.
// Callback signature: fn( WP_User $u ): string — defaults to $u->display_name.
->set_option_label(
fn( WP_User $u ) => sprintf( '%s <%s>', $u->display_name, $u->user_email )
)
// Override the value stored for each matched user.
// Callback signature: fn( WP_User $u ): string — defaults to (string) $u->ID.
->set_option_value( fn( WP_User $u ) => (string) $u->ID )
// Server-side validation — must resolve to a real user.
->set_validate( fn( $v ) => (bool) get_userdata( (int) $v ) );
Read the value back:
$owner_id = (int) $settings->get( 'site_owner' );
$owner = get_userdata( $owner_id );
Field-specific methods:
| Method | Purpose |
|---|---|
set_role( string ) | Restrict search to a single role slug. |
set_option_label( callable ) | fn( WP_User $u ): string — controls the displayed label. |
set_option_value( callable ) | fn( WP_User $u ): string — controls the stored value. |
Post_Picker
Setting\Field\Post_Picker — type-ahead search-and-pick for posts. The picker calls a bundled REST endpoint as the user types and stores the selected post’s ID.
Traits: Multiple, Data, Disabled, Placeholder, Query.
Post_Picker::new( 'featured' )
// Visible label above the picker.
->set_label( 'Featured Products' )
// Greyed-out hint shown inside the empty search box.
->set_placeholder( 'Search products...' )
// Help text rendered below the picker.
->set_description( 'Shown on the home page carousel.' )
// Required on submit.
->set_required()
// Allow multiple selections (value becomes an array of IDs).
->set_multiple()
// Shortcut — restrict the search to a single post type.
->set_post_type( 'product' )
// Full WP_Query args — takes precedence over set_post_type().
->set_query_args( array(
'post_type' => 'product',
'post_status' => 'publish',
'meta_query' => array(
array( 'key' => '_featured', 'value' => 'yes' ),
),
) )
// Disable the picker.
->set_disabled( false )
// Override the auto-generated HTML id.
->set_id( 'acme-featured' )
// Append a CSS class.
->add_class( 'is-product-picker' )
// data-* attributes for JS hooks.
->set_data( 'source', 'featured-products' )
// Override the label shown for each matched post.
// Callback signature: fn( WP_Post $p ): string — defaults to $p->post_title.
->set_option_label(
fn( WP_Post $p ) => sprintf( '%s (#%d)', $p->post_title, $p->ID )
)
// Server-side validation — must resolve to a published post.
->set_validate( fn( $v ) => 'publish' === get_post_status( (int) $v ) );
Read the value back:
$post_id = (int) $settings->get( 'featured' );
$post = get_post( $post_id );
Field-specific methods:
| Method | Purpose |
|---|---|
set_post_type( string ) | Shortcut for set_query_args( [ 'post_type' => … ] ). |
set_query_args( array ) | Full WP_Query arg list. Takes precedence over set_post_type(). |
set_option_label( callable ) | fn( WP_Post $p ): string — controls the displayed label. |
set_option_value( callable ) | fn( WP_Post $p ): string — controls the stored value. |
Composite
Repeater
Setting\Field\Repeater — repeating set of sub-fields. Values are stored as an array of arrays. Repeaters cannot be nested inside another repeater.
Traits: Disabled, Data.
Repeater::new( 'social_links' )
// Visible label above the repeater.
->set_label( 'Social Links' )
// Help text rendered below the repeater.
->set_description( 'Shown in the footer. Drag to reorder.' )
// Label on the "add row" button (default: 'Add').
->set_add_to_group_label( 'Add Link' )
// Layout of each row — 'row' (default) or 'columns'.
->set_layout( 'columns' )
// CSS class applied to each row wrapper (default: 'repeater-group').
->set_group_class( 'acme-social-row' )
// Child fields — any Field except another Repeater.
->add_field(
Text::new( 'platform' )
->set_label( 'Platform' )
->set_placeholder( 'Twitter' )
->set_required()
)
->add_field(
Url::new( 'url' )
->set_label( 'URL' )
->set_placeholder( 'https://twitter.com/acme' )
->set_required()
)
// Disable the whole repeater (adds / removes / edits all blocked).
->set_disabled( false )
// Override the auto-generated HTML id.
->set_id( 'acme-social' )
// Append a CSS class to the outer wrapper.
->add_class( 'is-repeater' )
// data-* attributes for JS hooks.
->set_data( 'max-rows', '10' )
// Server-side validation — must have at least one row.
->set_validate( fn( $v ) => is_array( $v ) && count( $v ) > 0 );
Field-specific methods:
| Method | Purpose |
|---|---|
add_field( Field ) | Add a child field. Throws if another repeater is passed. |
set_add_to_group_label( string ) | Label on the “add row” button. Default 'Add'. |
set_layout( string ) | 'row' (default) or 'columns'. |
set_group_class( string ) | CSS class applied to each row wrapper. Default 'repeater-group'. |