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

Custom Meta Box not Saving in Posts with Gutenberg Editor

programmeradmin6浏览0评论

I've read quite a bit of documentation around it, tons of other answers here, but I can't seem to discern why the custom meta box I'm trying to add to posts (and pages, but let's start with one at a time) isn't saving the post meta. I've got a custom CPT and it works perfectly. I've even used the Select2 method as part of theme options that allows me to assign up to 8 of the posts from my CPT to the front page. That works perfectly.

The issue I'm having is getting the traditional add_metabox method to save the selected posts from the CPT to the post meta. The Select2 works perfectly and I can search and select as many of the CPTs as I want. They display, when I click 'Update' on a post, the little wheel spins and it appears as though it HAS saved the post meta. However, the saved post meta does not appear in the database.

Here's what I have:

//REGISTER CPT META SO BLOCK EDITOR CAN SAVE IT TO POSTS
function mycpt_register_post_meta() {
    register_post_meta(
        'post',
        'mycpt_cpts',
        array(
            'show_in_rest' => true,
            'single' => true,
            'type' => 'string',
        )
    );
}
add_action( 'init', 'mycpt_register_post_meta' );

//ADD CPT SELECTION METABOX TO PAGES AND POSTS
function mycpt_add_cpt_selection() {
    $screens = ['page', 'post'];
    foreach( $screens as $screen ) {
        add_meta_box(
            'mycpt_assignment',
            'Assign Quick Links',
            'mycpt_assign_metabox',
            $screen,
            'side',
            'low',
             array(
                '__block_editor_compatible_meta_box' => true,
                '__back_compat_meta_box'             => false,
            )
        );
    }
}
add_action( 'add_meta_boxes', 'mycpt_add_ql_selection' );

//CPT SELECTION METABOX OPTIONS
function mycpt_assign_metabox( $post ) {
    wp_nonce_field( basename( __FILE__ ), 'mycpt_ql_nonce' );
    $mycpt_appended_cpts = get_post_meta( $post->ID, 'mycpt_cpts', false ); ?>
    <select id="mycpt_cpts" name="mycpt_cpts[]" multiple="multiple" style="width:90%;">
    <?php
    if ( mycpt_appended_cpts ) {
        foreach( $mycpt_appended_cpts as $cpt_id ) {
            $cpt_title = get_the_title( $cpt_id );
            $cpt_title = ( mb_strlen( $cpt_title ) > 50 ) ? mb_substr( $cpt_title, 0, 49 ) . '...' : $cpt_title;
            echo '<option value="' . $cpt_id . '" selected="selected">' . $cpt_title . '</option>';
        }
    }
    ?>
    </select>
    <small style="display:block;font-size:0.8em;width:95%;">
        Add some instructions here...
    </small>
<?php }

Eventually, I'm going to start building these as native blocks, but I've not done that yet and there's deadlines, etc, that I'm chasing. From all the documentation I've read, and other questions/answers here and elsewhere, this SHOULD work, but it doesn't. I just don't know what step I'm missing.

(For context, I want to allow the users to assign posts from the CPT to a post or a page, in the template, I will use the post meta to output a list of links to the CPTs in a sidebar.)

I've read quite a bit of documentation around it, tons of other answers here, but I can't seem to discern why the custom meta box I'm trying to add to posts (and pages, but let's start with one at a time) isn't saving the post meta. I've got a custom CPT and it works perfectly. I've even used the Select2 method as part of theme options that allows me to assign up to 8 of the posts from my CPT to the front page. That works perfectly.

The issue I'm having is getting the traditional add_metabox method to save the selected posts from the CPT to the post meta. The Select2 works perfectly and I can search and select as many of the CPTs as I want. They display, when I click 'Update' on a post, the little wheel spins and it appears as though it HAS saved the post meta. However, the saved post meta does not appear in the database.

Here's what I have:

//REGISTER CPT META SO BLOCK EDITOR CAN SAVE IT TO POSTS
function mycpt_register_post_meta() {
    register_post_meta(
        'post',
        'mycpt_cpts',
        array(
            'show_in_rest' => true,
            'single' => true,
            'type' => 'string',
        )
    );
}
add_action( 'init', 'mycpt_register_post_meta' );

//ADD CPT SELECTION METABOX TO PAGES AND POSTS
function mycpt_add_cpt_selection() {
    $screens = ['page', 'post'];
    foreach( $screens as $screen ) {
        add_meta_box(
            'mycpt_assignment',
            'Assign Quick Links',
            'mycpt_assign_metabox',
            $screen,
            'side',
            'low',
             array(
                '__block_editor_compatible_meta_box' => true,
                '__back_compat_meta_box'             => false,
            )
        );
    }
}
add_action( 'add_meta_boxes', 'mycpt_add_ql_selection' );

//CPT SELECTION METABOX OPTIONS
function mycpt_assign_metabox( $post ) {
    wp_nonce_field( basename( __FILE__ ), 'mycpt_ql_nonce' );
    $mycpt_appended_cpts = get_post_meta( $post->ID, 'mycpt_cpts', false ); ?>
    <select id="mycpt_cpts" name="mycpt_cpts[]" multiple="multiple" style="width:90%;">
    <?php
    if ( mycpt_appended_cpts ) {
        foreach( $mycpt_appended_cpts as $cpt_id ) {
            $cpt_title = get_the_title( $cpt_id );
            $cpt_title = ( mb_strlen( $cpt_title ) > 50 ) ? mb_substr( $cpt_title, 0, 49 ) . '...' : $cpt_title;
            echo '<option value="' . $cpt_id . '" selected="selected">' . $cpt_title . '</option>';
        }
    }
    ?>
    </select>
    <small style="display:block;font-size:0.8em;width:95%;">
        Add some instructions here...
    </small>
<?php }

Eventually, I'm going to start building these as native blocks, but I've not done that yet and there's deadlines, etc, that I'm chasing. From all the documentation I've read, and other questions/answers here and elsewhere, this SHOULD work, but it doesn't. I just don't know what step I'm missing.

(For context, I want to allow the users to assign posts from the CPT to a post or a page, in the template, I will use the post meta to output a list of links to the CPTs in a sidebar.)

Share Improve this question asked May 3, 2020 at 21:02 Tony DjukicTony Djukic 2,2774 gold badges19 silver badges34 bronze badges 1
  • I think I’ve solved this... will post an answer in case anyone can add to it or needs it in future. – Tony Djukic Commented May 3, 2020 at 22:48
Add a comment  | 

1 Answer 1

Reset to default 3

So, it simply turns out that the method I usually use to save post meta doesn't work in this context, even though it does in when using the classic editor. I don't know why this is, but I did find another article (https://www.codeinwp/blog/make-plugin-compatible-with-gutenberg-sidebar-api/) and there was a line in there that eventually led me to a solution. Additionally the entire, mycpt_register_post_meta() function doesn't appear to be necessary at all if you're saving data in this manner. For the clarification, I didn't actually show my usual saving method in my question because it wasn't working and I'd long since abandoned trying to use it in this particular instance - so I didn't include it. (If anyone wants to see it I can add it.)

function mycpt_add_cpt_selection() {
    $screens = ['page', 'post'];
    foreach( $screens as $screen ) {
        add_meta_box(
            'mycpt_assignment',
            'Assign Quick Links',
            'mycpt_assign_metabox',
            $screen,
            'side',
            'low',
             //not even sure that this array is necessary
             array(
                '__block_editor_compatible_meta_box' => true,
                '__back_compat_meta_box'             => false,
            )
        );
    }
}
add_action( 'add_meta_boxes', 'mycpt_add_cpt_selection' );
function mycpt_assign_metabox( $post ) {
    wp_nonce_field( basename( __FILE__ ), 'mycpt_cpt_nonce' );
    $mycpt_appended_cpts = get_post_meta( $post->ID, 'mycpt_cpts', false ); ?>
    <select id="mycpt_cpts" name="mycpt_cpts[]" multiple="multiple" style="width:90%;">
    <?php
    if( $mycpt_appended_cpts ) {
        foreach( $mycpt_appended_cpts as $cpt_ids ) {
            foreach( $cpt_ids as $cpt_id ) {
                $cpt_title = get_the_title( $cpt_id );
                $cpt_title = ( mb_strlen( $cpt_title ) > 50 ) ? mb_substr( $cpt_title, 0, 49 ) . '...' : $cpt_title;
                echo '<option value="' . $cpt_id . '" selected="selected">' . $cpt_title . '</option>';
            }
        }
    }
    ?>
    </select>
    <small style="display:block;font-size:0.8em;width:95%;">
        Instructions
    </small>
<?php }
function mycpt_assign_save_postdata( $post_id ) {
    if( isset( $_POST['mycpt_cpts'] ) ) {
        update_post_meta( $post_id, 'mycpt_cpts', $_POST['mycpt_cpts'] );
    }
}
add_action( 'save_post', 'mycpt_assign_save_postdata' );

So everything works almost exactly the way I want it. The only oddity that still perplexes me is when retrieving the post_meta it's actually putting an array into another array. It's creating a multi-dimensional array, which isn't what happens when I use the same methods in other areas.

As an example, in the database, when I've assigned four of my CPT posts to a WP post - it's saved as the following:

a:2:{i:0;s:2:"65";i:1;s:2:"66";}

Which would be:

array(
  0 => "65",
  1 => "66"
)

However, when I retrieve using get_post_meta(), what I get back is the following:

array(
  0 => array(
    0 => "65",
    1 => "66" 
  ),
)

You can see from select output that I have 2 foreach loops in there, so I've got a workaround, but I'm still going to figure out how to get it to return just a single array.

Hope someone else finds this useful.

发布评论

评论列表(0)

  1. 暂无评论