Skip to content

Use in Options Setting (Single Row Storage)

Wapiclo edited this page Dec 4, 2025 · 1 revision

This guide demonstrates how to store all plugin/theme settings in a single database row as an array, which provides better performance and cleaner database structure.

Why Store Settings in a Single Option Row?

Storing all settings in one option (as an array) provides several benefits:

Performance Benefits

  • Fewer database queries – Only one query to load all settings
  • Better caching – WordPress automatically caches the entire option
  • Faster page loads – Reduced database overhead

Maintenance Benefits

  • Cleaner database – Prevents option table bloat
  • Easier management – Add or remove fields without creating new options
  • Simpler export/import – All data is stored in a single structured array
  • Easier uninstall – Delete one option instead of many

Complete Example

Below is a complete example showing how to create an options page that stores all settings in a single database row.

<?php
/**
 * Example Options Page with Single Row Storage
 *
 * This demonstrates how to store all settings in a single
 * WordPress option as an array for better performance.
 *
 * @package Wapic_Fields
 */

namespace Wapic_Fields\Example;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

use Wapic_Fields\Field;

class Example_Options_Single_Row {

    /**
     * Page ID
     *
     * @var string
     */
    private $id = 'wapic-options-single-row';

    /**
     * Option name where all settings are stored
     *
     * @var string
     */
    private $option_name = '_example_options_single_row';

    /**
     * Constructor - Register hooks
     */
    public function __construct() {
        add_action( 'admin_menu', array( $this, 'register' ) );
    }

    /**
     * Get option value with fallback to default
     *
     * @param string $key     The option key to retrieve.
     * @param mixed  $default Default value if key doesn't exist.
     * @return mixed The option value or default.
     */
    private function get_option( $key, $default = '' ) {
        $options = get_option( $this->option_name, array() );
        $default = $default ?? '';
        return isset( $options[ $key ] ) ? $options[ $key ] : $default;
    }

    /**
     * Register Admin Menu Page
     *
     * Creates a settings page under WP Admin with Wapic Fields UI.
     */
    public function register() {
        add_menu_page(
            esc_html__( 'Wapic Fields Options Example', 'wapic-field' ),
            esc_html__( 'Wapic Fields', 'wapic-field' ),
            'manage_options',
            $this->id,
            array( $this, 'render' ),
            'dashicons-admin-generic',
            9999
        );

        // Register the single option with custom sanitization
        register_setting(
            $this->id,                 // Option group
            $this->option_name,        // Option name
            array(
                'sanitize_callback' => array( $this, 'sanitize_options' ),
            )
        );
    }

    /**
     * Sanitize all options before saving
     *
     * This method processes all fields, validates them,
     * and combines them into a single array.
     *
     * @param array $input The input array (not used directly).
     * @return array The sanitized options array.
     */
    public function sanitize_options( $input ) {
        // Get current options to preserve any existing values
        $output = get_option( $this->option_name, array() );

        // Define all fields and their types
        $fields = array(
            '_example_toggle' => 'toggle',
            '_example_text'   => 'text',
        );

        // Process each field
        foreach ( $fields as $field => $type ) {

            // Special handling for toggle fields
            if ( $type === 'toggle' ) {
                $output[ $field ] = ( isset( $_POST[ $field ] ) && $_POST[ $field ] === 'yes' ) ? 'yes' : 'no';
                continue;
            }

            // Process other field types
            if ( isset( $_POST[ $field ] ) ) {
                $value = $_POST[ $field ];

                // Skip validation if the field is hidden (conditional logic)
                if ( isset( $_POST[ $field . '_is_hidden' ] ) && $_POST[ $field . '_is_hidden' ] === '1' ) {
                    $output[ $field ] = Field::sanitize_value( $type, $value );
                    continue;
                }

                // Validate the value
                $validation = Field::validate_value( $type, $value );

                if ( empty( $validation ) ) {
                    // Validation passed - sanitize and save
                    $output[ $field ] = Field::sanitize_value( $type, $value );
                } else {
                    // Validation failed - show error
                    add_settings_error( $this->id, 'validation_error', $validation, 'error' );
                }
            }
        }

        return $output;
    }

    /**
     * Render the Settings Page
     *
     * Displays the settings form with fields.
     */
    public function render() {

        Field::start_controls_panel(
            array(
                'title' => esc_html__( 'Settings', 'wapic-fields' ),
                'id'    => $this->id,
                'type'  => 'setting',
            )
        );

        // Toggle field
        Field::add_control(
            array(
                'id'    => '_example_toggle',
                'type'  => 'toggle',
                'label' => esc_html__( 'Enable Feature', 'wapic-fields' ),
                'value' => $this->get_option( '_example_toggle', 'yes' ),
            )
        );

        // Text field
        Field::add_control(
            array(
                'id'    => '_example_text',
                'type'  => 'text',
                'label' => esc_html__( 'Example Text', 'wapic-fields' ),
                'value' => $this->get_option( '_example_text', '' ),
            )
        );

        Field::end_controls_panel(
            array(
                'type' => 'setting',
            )
        );
    }
}

// Initialize the options page
new Example_Options_Single_Row();

Retrieving Saved Values

Method 1: Direct Access

To retrieve settings stored as an array inside a single WordPress option:

<?php
// Get all settings
$settings = get_option( '_example_options_single_row', array() );

// Access individual values
echo ! empty( $settings['_example_toggle'] ) ? $settings['_example_toggle'] : 'no';
echo ! empty( $settings['_example_text'] ) ? $settings['_example_text'] : '';

Method 2: Using a Helper Function (Recommended)

Create a custom helper function to simplify accessing values:

<?php
if ( ! function_exists( 'wapic_field_get_option' ) ) {
    /**
     * Get a specific option from the single row storage
     *
     * @param string $option_name The option key to retrieve.
     * @param mixed  $default     Default value if key doesn't exist.
     * @return mixed The option value or default.
     */
    function wapic_field_get_option( $option_name, $default = null ) {
        // Replace with your actual option name
        $options = get_option( '_example_options_single_row', array() );
        
        return isset( $options[ $option_name ] ) ? $options[ $option_name ] : $default;
    }
}

Usage Example:

<?php
// Get individual values with defaults
$toggle_value = wapic_field_get_option( '_example_toggle', 'no' );
$text_value   = wapic_field_get_option( '_example_text', 'Default text' );

// Use in your template
if ( $toggle_value === 'yes' ) {
    echo '<p>' . esc_html( $text_value ) . '</p>';
}

Key Differences from Standard Options

Aspect Standard Options Single Row Storage
Database rows One per option One for all options
Database queries Multiple queries Single query
Performance Slower with many options Faster, better caching
Retrieval get_option('field_name') get_option('option_name')['field_name']
Cleanup Delete each option individually Delete one option

Best Practices

  1. Use a Helper Function: Create a helper function to simplify value retrieval
  2. Consistent Naming: Use a consistent prefix for all field keys (e.g., _example_)
  3. Default Values: Always provide default values when retrieving options
  4. Documentation: Document the structure of your options array
  5. Validation: Always validate and sanitize input in the sanitize_options() method

Adding More Fields

To add more fields, simply:

  1. Add the field to the $fields array in sanitize_options():
$fields = array(
    '_example_toggle' => 'toggle',
    '_example_text'   => 'text',
    '_example_email'  => 'email',  // New field
);
  1. Add the field control in the render() method:
Field::add_control(
    array(
        'id'    => '_example_email',
        'type'  => 'email',
        'label' => esc_html__( 'Email Address', 'wapic-fields' ),
        'value' => $this->get_option( '_example_email', '' ),
    )
);

Next Steps

Clone this wiki locally