PHPackages                             arraypress/wp-register-user-fields - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. arraypress/wp-register-user-fields

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

arraypress/wp-register-user-fields
==================================

Lightweight library for registering custom fields on WordPress user profile screens.

113PHP

Since Feb 23Pushed 2mo agoCompare

[ Source](https://github.com/arraypress/wp-register-user-fields)[ Packagist](https://packagist.org/packages/arraypress/wp-register-user-fields)[ RSS](/packages/arraypress-wp-register-user-fields/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

WordPress Register User Fields
==============================

[](#wordpress-register-user-fields)

A lightweight library for registering custom fields on WordPress user profile and Add New User screens. This library provides a clean, simple API for adding common field types to user profiles without JavaScript dependencies or complex configuration.

Features
--------

[](#features)

- **Simple API**: Register custom user fields with minimal code
- **Multiple Field Types**: Text, textarea, number, select, checkbox, URL, and email
- **Automatic Saving**: Fields are automatically saved to user meta
- **Smart Sanitization**: Each field type has appropriate default sanitization
- **Dynamic Options**: Select fields support callable options for dynamic data
- **Section Grouping**: Group related fields under custom section headings
- **Add New User Support**: Fields appear on the Add New User screen
- **Permission Control**: Control field visibility based on user capabilities
- **No JavaScript**: Pure PHP implementation with WordPress-native markup
- **Lightweight**: Single class, minimal footprint

Requirements
------------

[](#requirements)

- PHP 7.4 or higher
- WordPress 5.0 or higher

Installation
------------

[](#installation)

Install via Composer:

```
composer require arraypress/wp-register-user-fields
```

Basic Usage
-----------

[](#basic-usage)

### Simple Text Fields

[](#simple-text-fields)

```
register_user_fields( [
    'company' => [
        'label'       => __( 'Company', 'textdomain' ),
        'type'        => 'text',
        'description' => __( 'Your company or organization name.', 'textdomain' ),
    ],
    'job_title' => [
        'label'       => __( 'Job Title', 'textdomain' ),
        'type'        => 'text',
        'placeholder' => __( 'e.g., Senior Developer', 'textdomain' ),
    ],
] );
```

### Custom Section Title

[](#custom-section-title)

```
register_user_fields( [
    'department' => [
        'label'   => __( 'Department', 'textdomain' ),
        'type'    => 'select',
        'options' => [
            ''          => __( '— Select —', 'textdomain' ),
            'sales'     => __( 'Sales', 'textdomain' ),
            'support'   => __( 'Support', 'textdomain' ),
            'dev'       => __( 'Development', 'textdomain' ),
            'marketing' => __( 'Marketing', 'textdomain' ),
        ],
    ],
    'employee_id' => [
        'label' => __( 'Employee ID', 'textdomain' ),
        'type'  => 'text',
    ],
], __( 'Employee Information', 'textdomain' ) );
```

### Multiple Field Groups

[](#multiple-field-groups)

Register multiple groups with different section titles:

```
// Contact information
register_user_fields( [
    'phone' => [
        'label'       => __( 'Phone', 'textdomain' ),
        'type'        => 'text',
        'placeholder' => '+1 (555) 000-0000',
    ],
    'extension' => [
        'label' => __( 'Extension', 'textdomain' ),
        'type'  => 'number',
        'min'   => 100,
        'max'   => 9999,
    ],
], __( 'Contact Information', 'textdomain' ) );

// Social profiles
register_user_fields( [
    'linkedin' => [
        'label'       => __( 'LinkedIn URL', 'textdomain' ),
        'type'        => 'url',
        'placeholder' => 'https://linkedin.com/in/username',
    ],
    'twitter' => [
        'label'       => __( 'Twitter/X Handle', 'textdomain' ),
        'type'        => 'text',
        'placeholder' => '@username',
    ],
], __( 'Social Profiles', 'textdomain' ) );
```

### Select with Dynamic Options

[](#select-with-dynamic-options)

```
register_user_fields( [
    'manager_id' => [
        'label'       => __( 'Reports To', 'textdomain' ),
        'type'        => 'select',
        'description' => __( 'Select your direct manager.', 'textdomain' ),
        'options'     => function() {
            $managers = get_users( [
                'role__in' => [ 'administrator', 'editor' ],
                'orderby'  => 'display_name',
            ] );

            $options = [ '' => __( '— Select Manager —', 'textdomain' ) ];

            foreach ( $managers as $manager ) {
                $options[ $manager->ID ] = $manager->display_name;
            }

            return $options;
        },
    ],
] );
```

Field Types
-----------

[](#field-types)

### Text

[](#text)

Standard single-line text input.

```
'field_name' => [
    'label'       => __( 'Field Label', 'textdomain' ),
    'type'        => 'text',
    'placeholder' => __( 'Placeholder text...', 'textdomain' ),
    'default'     => '',
]
```

### Textarea

[](#textarea)

Multi-line text input.

```
'bio' => [
    'label'       => __( 'Biography', 'textdomain' ),
    'type'        => 'textarea',
    'rows'        => 5,
    'placeholder' => __( 'Tell us about yourself...', 'textdomain' ),
]
```

### Number

[](#number)

Numeric input with optional constraints.

```
'years_experience' => [
    'label'   => __( 'Years of Experience', 'textdomain' ),
    'type'    => 'number',
    'min'     => 0,
    'max'     => 50,
    'step'    => 1,
    'default' => 0,
]
```

For decimal values, set a decimal step:

```
'hourly_rate' => [
    'label' => __( 'Hourly Rate', 'textdomain' ),
    'type'  => 'number',
    'min'   => 0,
    'step'  => 0.01,
]
```

### Select

[](#select)

Dropdown selection with static or dynamic options.

```
// Static options
'status' => [
    'label'   => __( 'Status', 'textdomain' ),
    'type'    => 'select',
    'default' => 'active',
    'options' => [
        'active'   => __( 'Active', 'textdomain' ),
        'inactive' => __( 'Inactive', 'textdomain' ),
        'pending'  => __( 'Pending', 'textdomain' ),
    ],
]

// Dynamic options via callback
'location' => [
    'label'   => __( 'Office Location', 'textdomain' ),
    'type'    => 'select',
    'options' => function() {
        // Could query from database, API, etc.
        return [
            ''       => __( '— Select —', 'textdomain' ),
            'nyc'    => __( 'New York', 'textdomain' ),
            'london' => __( 'London', 'textdomain' ),
            'tokyo'  => __( 'Tokyo', 'textdomain' ),
        ];
    },
]
```

### Checkbox

[](#checkbox)

Boolean toggle field.

```
'subscribe_newsletter' => [
    'label'       => __( 'Subscribe to Newsletter', 'textdomain' ),
    'type'        => 'checkbox',
    'default'     => 0,
    'description' => __( 'Receive weekly updates via email.', 'textdomain' ),
]
```

### URL

[](#url)

Text input with URL validation.

```
'website' => [
    'label'       => __( 'Personal Website', 'textdomain' ),
    'type'        => 'url',
    'placeholder' => 'https://example.com',
]
```

### Email

[](#email)

Text input with email validation.

```
'alternate_email' => [
    'label'       => __( 'Alternate Email', 'textdomain' ),
    'type'        => 'email',
    'placeholder' => 'alternate@example.com',
    'description' => __( 'Secondary contact email address.', 'textdomain' ),
]
```

Field Configuration Options
---------------------------

[](#field-configuration-options)

Each field accepts the following configuration options:

OptionTypeDefaultDescription`label`string`''`Field label text`type`string`'text'`Field type`description`string`''`Help text displayed below the field`default`mixed`''`Default value for new users`placeholder`string`''`Placeholder text for text inputs`options`array|callable`[]`Options for select fields`min`int|float`null`Minimum value for number fields`max`int|float`null`Maximum value for number fields`step`int|float`null`Step increment for number fields`rows`int`5`Number of rows for textarea fields`sanitize_callback`callable`null`Custom sanitization function`capability`string`'edit_users'`Required capability to view/edit the field`show_in_admin`bool`true`Show field when editing other users`show_in_profile`bool`true`Show field on own profileRetrieving Field Values
-----------------------

[](#retrieving-field-values)

### Standard Method

[](#standard-method)

Use WordPress's built-in function:

```
$company = get_user_meta( $user_id, 'company', true );
```

### With Default Fallback

[](#with-default-fallback)

Use the helper function to automatically fall back to registered defaults:

```
$department = get_user_field_value( $user_id, 'department' );
```

### Get All Registered Fields

[](#get-all-registered-fields)

```
$all_fields = get_all_user_fields();

foreach ( $all_fields as $group_id => $fields ) {
    foreach ( $fields as $meta_key => $config ) {
        echo $config['label'] . ': ' . get_user_meta( $user_id, $meta_key, true );
    }
}
```

### Get Field Configuration

[](#get-field-configuration)

```
$config = get_user_field_config( 'department' );

if ( $config ) {
    echo 'Label: ' . $config['label'];
    echo 'Type: ' . $config['type'];
}
```

Custom Sanitization
-------------------

[](#custom-sanitization)

Override the default sanitization for any field:

```
register_user_fields( [
    'custom_html' => [
        'label'             => __( 'Custom Bio', 'textdomain' ),
        'type'              => 'textarea',
        'sanitize_callback' => function( $value ) {
            return wp_kses( $value, [
                'p'      => [],
                'br'     => [],
                'strong' => [],
                'em'     => [],
                'a'      => [ 'href' => [], 'title' => [] ],
            ] );
        },
    ],
] );
```

Permission Control
------------------

[](#permission-control)

Control field visibility based on user capabilities:

```
register_user_fields( [
    'salary' => [
        'label'       => __( 'Salary', 'textdomain' ),
        'type'        => 'number',
        'capability'  => 'manage_options', // Only administrators
        'description' => __( 'Annual salary (admin only).', 'textdomain' ),
    ],
    'notes' => [
        'label'      => __( 'HR Notes', 'textdomain' ),
        'type'       => 'textarea',
        'capability' => 'edit_users',
        'show_in_profile' => false, // Don't show to user on their own profile
    ],
] );
```

Complete Example
----------------

[](#complete-example)

```
// Employee information
register_user_fields( [
    'employee_id' => [
        'label'       => __( 'Employee ID', 'textdomain' ),
        'type'        => 'text',
        'placeholder' => 'EMP-0000',
    ],
    'department' => [
        'label'   => __( 'Department', 'textdomain' ),
        'type'    => 'select',
        'options' => [
            ''          => __( '— Select —', 'textdomain' ),
            'sales'     => __( 'Sales', 'textdomain' ),
            'support'   => __( 'Support', 'textdomain' ),
            'dev'       => __( 'Development', 'textdomain' ),
            'hr'        => __( 'Human Resources', 'textdomain' ),
        ],
    ],
    'start_date' => [
        'label'       => __( 'Start Date', 'textdomain' ),
        'type'        => 'text',
        'placeholder' => 'YYYY-MM-DD',
    ],
    'manager_id' => [
        'label'   => __( 'Manager', 'textdomain' ),
        'type'    => 'select',
        'options' => function() {
            $users   = get_users( [ 'role' => 'administrator' ] );
            $options = [ '' => __( '— None —', 'textdomain' ) ];
            foreach ( $users as $user ) {
                $options[ $user->ID ] = $user->display_name;
            }
            return $options;
        },
    ],
    'remote_worker' => [
        'label'       => __( 'Remote Worker', 'textdomain' ),
        'type'        => 'checkbox',
        'description' => __( 'This employee works remotely.', 'textdomain' ),
    ],
], __( 'Employee Information', 'textdomain' ) );

// Contact details
register_user_fields( [
    'phone' => [
        'label'       => __( 'Phone', 'textdomain' ),
        'type'        => 'text',
        'placeholder' => '+1 (555) 000-0000',
    ],
    'extension' => [
        'label' => __( 'Extension', 'textdomain' ),
        'type'  => 'number',
        'min'   => 100,
        'max'   => 9999,
    ],
    'slack_handle' => [
        'label'       => __( 'Slack Handle', 'textdomain' ),
        'type'        => 'text',
        'placeholder' => '@username',
    ],
], __( 'Contact Information', 'textdomain' ) );

// Usage in templates
$user_id     = get_current_user_id();
$department  = get_user_field_value( $user_id, 'department' );
$is_remote   = get_user_meta( $user_id, 'remote_worker', true );
$employee_id = get_user_meta( $user_id, 'employee_id', true );
```

Integration with Register Columns
---------------------------------

[](#integration-with-register-columns)

This library pairs well with [wp-register-columns](https://github.com/arraypress/wp-register-columns) to display user field values in the admin users list:

```
// Register the field
register_user_fields( [
    'department' => [
        'label'   => __( 'Department', 'textdomain' ),
        'type'    => 'select',
        'options' => [
            'sales'   => 'Sales',
            'support' => 'Support',
            'dev'     => 'Development',
        ],
    ],
] );

// Display in users list table
register_user_columns( [
    'department' => [
        'label'            => __( 'Department', 'textdomain' ),
        'meta_key'         => 'department',
        'sortable'         => true,
        'display_callback' => function( $value, $user_id ) {
            return ucfirst( $value ) ?: '—';
        },
    ],
] );
```

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

License
-------

[](#license)

GPL-2.0-or-later

Author
------

[](#author)

David Sherlock - [ArrayPress](https://arraypress.com/)

Support
-------

[](#support)

- [Documentation](https://github.com/arraypress/wp-register-user-fields)
- [Issue Tracker](https://github.com/arraypress/wp-register-user-fields/issues)

###  Health Score

21

—

LowBetter than 18% of packages

Maintenance56

Moderate activity, may be stable

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity12

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/cd6eb8aff0903d87eb674d1ba3c5f3653899c0d7661504eb0deb7798ed86b643?d=identicon)[arraypress](/maintainers/arraypress)

---

Top Contributors

[![arraypress](https://avatars.githubusercontent.com/u/22668877?v=4)](https://github.com/arraypress "arraypress (2 commits)")

### Embed Badge

![Health badge](/badges/arraypress-wp-register-user-fields/health.svg)

```
[![Health](https://phpackages.com/badges/arraypress-wp-register-user-fields/health.svg)](https://phpackages.com/packages/arraypress-wp-register-user-fields)
```

###  Alternatives

[alexpechkarev/geometry-library

PHP Geometry library provides utility functions for the computation of geometric data on the surface of the Earth.

1393.6M6](/packages/alexpechkarev-geometry-library)

PHPackages © 2026

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