Register some custom settings in WordPress
Tags: wordpress, wpgraphql
Published: 2019-05-15 07:11:59

Lately I played a lot with *WPGraphQL* a plugin that enables a *GraphQL API* for *WordPress*.
And I needed to retrieve links to social networks in my app.

Historically I would have done that with the [Customizer API](https://codex.wordpress.org/Theme_Customization_API), but **WPGraphQL** doesn't expose for the moment this data.

So, thanks to the **WPGraphQL** doc, an another idea came to me: used the [Settings API](https://codex.wordpress.org/Settings_API). WPGraphQL exposes all core settings in the WPGraphQL Schema.

So I thought that documented could be useful to anyone, even outside WPGraphQL ecosystem.

### Settings API

Three functions are essential to accomplish what you want: 
- [add_settings_section](https://developer.wordpress.org/reference/functions/add_settings_section/), used to define new settings sections for an admin page ;
- [add_settings_field](https://developer.wordpress.org/reference/functions/add_settings_field/), used to define a settings field ;
- [register_setting](https://developer.wordpress.org/reference/functions/register_setting/), to register settings and data.

### Settings class

We are going to write a PHP class named `Settings`:

```php
class Settings {
    /**
     * The theme name
     */
    protected $theme_name;
    
    /**
     * The theme version
     */
    protected $theme_version;
    
    /**
     * The constructor
     */
    public function __construct( $theme_name, $theme_version ) {
        $this->theme_name    = $theme_name;
        $this->theme_version = $theme_version;
    }
}
```

This class will be instantiated in the `functions.php` of our theme (or plugin).


### Settings API init method

So we are going to write a method for our `Settings` class to add settings:

```php
public function settings_api_init() {
    add_settings_section(
        'socials',
        'Socials',
        // In class context pass an array with $this and the method name
        // to retrieve callback function.
        array( $this, 'socials_callback_function' ),
        // Our Socials setting will be set under the General tab.
        'general'
    );

    add_settings_field(
        'twitter',
        'Twitter',
        array( $this, 'setting_callback_function' ),
        'general',
        // Display this setting under our newly declared section right
        // above.
        'socials',
        // Extra arguments used in callback function.
        array(
            'name'  => 'twitter',
            'label' => 'Twitter',
        )
    );
}

```

### Callback method

`add_settings_section` and `add_settings_field` take a callback function, `socials_callback_function` and `setting_callback_function` respectively, add them to our class:

```php
public function socials_callback_function() {
    echo '<p>Socials urls</p>';
}

public function setting_callback_function( $args ) {
    // Ugly, I know 😔.
    echo '<input name="' . esc_attr( $args['name'] ) . '" type="text" value="' . esc_attr( get_option( $args['name'] ) ) . '" class="regular-text code" placeholder="' . esc_attr( $args['label'] ) . ' URL" />'; 
    echo ' ' . esc_attr( $args['label'] ) . ' URL';
}

``` 

### Register settings method

Next, we are going to register this settings, so WordPress can handle this:

```php
public function register_settings() {
    $args = array(
        'type'              => 'string',
        'sanitize_callback' => 'sanitize_text_field',
        'default'           => null,
        // Extra argument for WPGraphQL.
        'show_in_graphql'   => true,
        'show_in_rest'      => true,
     );

     register_setting( 'general', 'twitter', $args );
}
```

### Constructor

Finally in our constructor, we can attach this methods to the class in appropriate hook:

```php

public function __construct( $theme_name, $theme_version ) {
    $this->theme_name    = $theme_name;
    $this->theme_version = $theme_version;

    add_action( 'admin_init', array( $this, 'settings_api_init' ) );
    // We hook into init and not admin_init to make front aware of this
    // settings.
    add_action( 'init', array( $this, 'register_settings' ) );
}

```

Now, we can instantiate our `Settings` class in `functions.php` and retrieve our settings in the general setting page. 

![WordPress custom settings](https://thepracticaldev.s3.amazonaws.com/i/yx22sbpqtxuoj0xcr8ul.jpg)

Cool right? And without any plugin. 😎

### Conclusion

Of course, we can go further, used other type of input, display a selection of pages, display some checkboxes. We can do whatever we want!

Feel free to correct me if you see any typo or ask if you have any questions.

–
<small>To retrieve the entire class, follow this [link](https://gist.github.com/19h47/2e0e03a3caede1c258d95a5d7f7e16e3)</small>

–
#### Bonus WPGraphQL

Now that our settings are register, under the `generalSettings` entry, we will find our parameters:

```

generalSettings {
    twitter
}

```