最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

options - Serialized settings in rest api

programmeradmin1浏览0评论

I have registered settings and need it to be showed in REST API.

$args = [
    'show_in_rest' => true
];
register_setting('default_sidebars', 'default_sidebars', $args);

When I save a single value and then request data on endpoint /wp-json/wp/v2/settings, everything works perfectly.

But the problem is that I save serialized data like this.

a:2:{s:4:"post";s:7:"general";s:4:"blog";s:9:"sidebar_1";}

Now I would expect in response something like this:

default_sidebars: {
  post: "general",
  blog: "sidebar_1"
}

But instead I got default_sidebars: null.

What should I do to get my data in REST API?

I have registered settings and need it to be showed in REST API.

$args = [
    'show_in_rest' => true
];
register_setting('default_sidebars', 'default_sidebars', $args);

When I save a single value and then request data on endpoint /wp-json/wp/v2/settings, everything works perfectly.

But the problem is that I save serialized data like this.

a:2:{s:4:"post";s:7:"general";s:4:"blog";s:9:"sidebar_1";}

Now I would expect in response something like this:

default_sidebars: {
  post: "general",
  blog: "sidebar_1"
}

But instead I got default_sidebars: null.

What should I do to get my data in REST API?

Share Improve this question asked Mar 7, 2020 at 15:09 Tomáš VavřinkaTomáš Vavřinka 1979 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 6

JSON Schema

It's supported if you explicitly register the object JSON schema as:

$args = array(
    'show_in_rest' => array(
        'schema' => array(
            'type'       => 'object',
            'properties' => array(
                'post' => array(
                    'type' => 'string',
                ),
                'blog' => array(
                    'type' => 'string',
                ),
            )
        ),
    ),
);

register_setting( 'default_sidebars', 'default_sidebars', $args );

Resulting in the following object:

default_sidebars: {
  post: "general",
  blog: "sidebar_1"
}

in /wp-json/wp/v2/settings for the serialized option data:

a:2:{s:4:"post";s:7:"general";s:4:"blog";s:9:"sidebar_1";}

See similar object schema support for register_meta() in 5.3:

https://make.wordpress/core/2019/10/03/wp-5-3-supports-object-and-array-meta-types-in-the-rest-api/

Not sure if there's a better way when using the default Settings endpoint, but this works for me.

You can use the rest_pre_get_setting hook to convert the data to a JSON-encoded string:

add_filter( 'rest_pre_get_setting', function ( $value, $name ) {
    if ( 'default_sidebars' === $name ) {
        $value = json_encode( get_option( $name ) );
    }
    return $value;
}, 10, 2 );

Then for example in JavaScript, you can parse the value into an object using JSON.parse():

// Note: I intentionally omitted the authentication/nonce part.
fetch( 'https://example/wp-json/wp/v2/settings' )
    .then( res => res.json() )
    .then( settings => console.log( JSON.parse( settings.default_sidebars ) ) );

Or in PHP (e.g. you make the API request from another site using PHP), you can do:

$settings = json_decode( $data ); // assume data is the REST API response body
$default_sidebars = json_decode( $settings->default_sidebars );

Additional Notes

The null value is because get_option() unserializes the data to an array and the REST API controller for the Settings endpoint is using rest_validate_value_from_schema() to validate the option value (i.e. after being unserialized), which when it's not of the currently supported types (string, boolean, integer and number) — see register_setting(), then the function returns an error and the Settings endpoint/controller returns a null for that specific option.

Alternate Solution

You can create a custom REST API endpoint and with the following example, you would make request to /wp-json/myplugin/v1/setting/<option name> where <option name> could be default_sidebars in your case:

add_action( 'rest_api_init', function () {
    register_rest_route( 'myplugin/v1', '/setting/(?P<name>[a-zA-Z0-9\-_]+)', [
        'methods'  => 'GET',
        'callback' => function ( $request ) {
            return get_option( $request->get_param( 'name' ) );
        },
        'permission_callback' => function () {
            return current_user_can( 'manage_options' ); // you should keep this
        },
    ] );
} );
发布评论

评论列表(0)

  1. 暂无评论