从(经典的)序列化定制元字段转换到(Gutenberg)启用REST的元字段

时间:2019-03-06 作者:Vlad

我有一个自定义元框,用于将两个输入字段中的值保存到单个post元字段中。

数据以序列化方式保存在数据库中:

get_post_meta( $post->ID, \'_custom_key\', true )
将返回:

a:2:{s:5:"email";s:10:"[email protected]";s:6:"number";i:15;}
现在,使用Gutenberg,我想将整个自定义元框移动到一个单独的边栏插件中。所以为了做到这一点,首先,我必须添加__back_compat_meta_box 参数,因此它不会出现在Sidebar -> Settings -> Document 还有:

    add_meta_box(
        \'options\',
        \'Options\',
        [ $this, \'renderOptionsBox\' ],
        [ \'post\', \'page\', \'attachement\' ], // the meta field is registered for multiple post types 
        \'side\',
        \'high\',
        [ \'__back_compat_meta_box\' => true ]
    );
对于元字段(_custom_key) 要使用块编辑器,必须使用register_meta 功能:

register_meta( string $object_type, string $meta_key, array $args, string|array $deprecated = null )
我的问题是:

如何注册的自定义元字段all 此列表中的帖子类型[ \'post\', \'page\', \'attachement\' ]?type)只有“string”、“boolean”、“integer”和“number”,那么我如何仍然遵循相同的序列化方式将数据保存在单个字段中_custom_key 元使用:

    register_meta( \'post\', \'_custom_key\', [
        \'show_in_rest\' => true,
        \'single\' => true,
        \'type\' => \'string\',
        \'auth_callback\' => function () {
            return current_user_can( \'edit_posts\' );
        }
    ]);
我会得到一个Notice: Array to string conversion in .../wp-includes/rest-api/fields/class-wp-rest-meta-fields.php 因为已从数据库保存的数据已序列化。

并在控制台中键入:wp.data.select( \'core/editor\' ).getCurrentPost().meta; 将返回字符串:{_custom_key: "Array"}.

2 个回复
SO网友:rsborn

下面是问题1的答案,使用register_post_meta. 这也是通过使用prepare_callback 中的选项show_in_rest .

add_action( \'init\', \'wpse_89033_register_custom_meta\' );
function wpse_89033_register_custom_meta() {

    $post_types = [ 
        \'post\',
        \'page\',
        \'attachment\',
    ];

    foreach ( $post_types as $post_type ) {

        register_post_meta( 
            $post_type,
            \'_custom_key\',
            array(
                \'type\'              => \'string\',
                \'single\'            => true,
                \'auth_callback\'     => function() { 
                    return current_user_can( \'edit_posts\' );
                },
                \'show_in_rest\'      => [
                    \'prepare_callback\' => function( $value ) {
                        return wp_json_encode( $value );
                    }
                ],
            ) 
        );

    }

}
的文档show_in_rest (参见register_meta) 表示这是一个布尔参数。但它将接受选项数组。要查看选项,请查看get_registered_fields, 尤其是$default_args. 这个prepare_callback 覆盖prepare_value, 中的方法WP_REST_Meta_Fields 将自定义元值从数组转换为字符串。通过回调,该数组将被编码为JSON。

在JavaScript方面,下面是一些关键声明。

// Get the custom meta
let customMeta = wp.data.select(\'core/editor\').getEditedPostAttribute(\'meta\');

// Parse the meta so you can do some JS with it
let parsed = JSON.parse(customMeta._custom_key);

// Do some JS with the parsed meta...

// Stringify the parsed meta before dispatching it
let stringified = JSON.stringify(parsed);

/*
 * Dispatch (update) the meta (and don\'t forget to
 * save/publish/update the post to ensure the meta goes in the database)
 */ 
wp.data.dispatch(\'core/editor\').editPost({meta: {_custom_key: stringified}}); 
回到PHP领域,获取和更新您的自定义元现在将以不同的方式工作。当你打电话的时候get_post_meta, 您已经习惯了使用数组,有时可能仍然需要一个数组。但是,如果您上次通过WP-restapi更新了您的自定义元,那么您将得到一个JSON字符串。在这种情况下,您必须使用json_decode. 一种方法是将调用包装到get_post_meta 像这样:

function wpse_89033_get_custom_meta( $post_id, $meta_key ) {

    $post_meta = get_post_meta( $post_id, $meta_key, true );

    // If $post_meta is a string that\'s not empty
    if ( $post_meta && is_string( $post_meta ) ) {

        /*
         * Use the decoded JSON string or else the original string 
         * if decoding fails, e.g., if the string isn\'t JSON
         */ 
        $post_meta = json_decode( $post_meta, true ) ?: $post_meta;

    }

    return $post_meta;

}
如果您将自定义元更改为数组,则在调用之前不要担心重新编码update_post_meta. 这个prepare_callback 将处理重新编码。

关于在PHP中更新,调用update_post_meta 在期间save_post, 如中所示official plugin handbook, 似乎覆盖通过WP REST API进行的更新。所以还有一件事需要考虑save_post 更新自定义meta,了解文章是否正在古腾堡编辑。如果是,则将更新留给REST API。

SO网友:shazahm1

在WordPress 5.3中,您现在可以使用arrayobject 元类型。以下是Make WordPress Core的帖子,其中给出了所有细节和示例: