我正在尝试更新用户元,但始终为1,我哪里做错了?

时间:2019-01-08 作者:pawel1993
<?php function consultation_user_profile_fields($user){
if ( user_can( $user->ID, "subscriber" ) ) {
?>
    <h3>Consultation</h3>
    <?php $query = new WP_Query(
        array(
            \'posts_per_page\' => -1,
            \'post_type\' => \'consultation\',
            \'post_status\' => \'publish\'
        )
    );
    if ($query->have_posts()) :
        while($query->have_posts()) : $query->the_post(); 
        $hasAccess = \'\';
        if ( is_object( $user ) && isset( $user->ID ) ) {

            $hasAccess = get_user_meta( 
                           $user>ID,\'consultation\'.get_the_ID(), true );

        } ?>
        <div class="consultation">
            <span>Has access&nbsp;</span>
            <div class="title"><?php the_title(); ?></div>
            <input type="checkbox" id="consultation[<?= get_the_ID(); ?>]" 
            class="regular-text" name="consultation[<?= get_the_ID(); ?>]" 
            value="1" <?= ($hasAccess == 1 ? \'checked\' : \'\'); ?>/>
        </div>
    <?php endwhile; endif;
    } else {
        return;
    }
}
add_action( \'show_user_profile\', \'consultation_user_profile_fields\' );
add_action( \'edit_user_profile\', \'consultation_user_profile_fields\' );
add_action( "user_new_form", "consultation_user_profile_fields" );
function save_consultation_user_profile_fields($user_id){
    if(!current_user_can(\'manage_options\'))
        return false;

    foreach ($_POST[\'consultation\'] as $key => $val) {
        update_user_meta($user_id,\'consultation\'.$key,$_POST[\'consultation\'][$key]);
    }
# save my custom field

}
add_action( \'user_register\', \'save_consultation_user_profile_fields\');
add_action(\'personal_options_update\',\'save_consultation_user_profile_fields\' );
add_action( \'edit_user_profile_update\',\'save_consultation_user_profile_fields\' );
2 个回复
最合适的回答,由SO网友:Krzysiek Dróżdż 整理而成

您的user\\u meta未更新,因为您处理复选框不正确。。。

首先您已将所有复选框的值设置为1。因此,如果选中它们,则它们的值为1-这是保存为user\\u meta的值。

另一方面,如果未选中该复选框,则不会在POST请求中发送该复选框。所以你的foreach 循环不会在它们之间循环-因此user\\u meta将永远不会设置为除1之外的任何值;)

How to fix it?

您不应该迭代发布的数组,而应该循环发布。在该循环中,您应该检查POST请求中是否设置了给定值,并正确处理它(如果设置了值,则将user\\u meta设置为1,如果未设置值,则将其设置为0)。

此外,您不应该如此信任用户输入-如果用户篡改数据并在复选框中对ID进行一些更改,该怎么办?他可以访问其他帖子;)

所以我会这样做:

function save_consultation_user_profile_fields( $user_id ) {
    # save my custom field
    if( ! current_user_can(\'manage_options\') )
        return false;

    $query = new WP_Query(  // it\'s the same query you use to create checkboxes in form
        array(
            \'posts_per_page\' => -1,
            \'post_type\' => \'consultation\',
            \'post_status\' => \'publish\'
        )
    );
    foreach ( $query->posts as $post ) {
        if ( isset( $_POST[\'consultation\'][$post->ID] ) && 1 == $_POST[\'consultation\'][$post->ID] ) {
            update_user_meta( $user_id, \'consultation\' . $post->ID, 1 );
        } else {
            delete_user_meta( $user_id, \'consultation\' . $post->ID, 1 );
        }
    }
}
通过这种方式,您可以确保用户只能访问现有帖子。你们也会对数据库更友好——若用户并没有访问post的权限,那个么数据库中就并没有元数据存储。

SO网友:Jacob Peattie

问题是,当复选框未选中时,$_POST[\'consultation\'][$key] 该密钥不存在未选中复选框不会显示任何值

所以$_POST[\'consultation\'] 将仅包含选中复选框的值。这意味着其他复选框的现有保存值不会更改。

为未选中复选框发布值的最简单方法是在其前面有一个具有相同名称和不同值的隐藏输入。像这样:

<input type="hidden" name="consultation[<?= get_the_ID(); ?>]" value="0">
<input 
    type="checkbox" id="consultation[<?= get_the_ID(); ?>]" 
    class="regular-text" name="consultation[<?= get_the_ID(); ?>]" 
    value="1" <?= ($hasAccess == 1 ? \'checked\' : \'\'); ?>
/>
或者少重复你自己:

printf(
    \'<input id="%1$s" name="%1$s" type="hidden" value="0">
    <input name="%1$s" type="checkbox" value="1" %2$s>\',
    esc_attr( \'consultation[\' . get_the_ID() . \']\' ),
    checked( \'1\', $hasAccess, false )
);
现在如果复选框未选中,$_POST[\'consultation\'][$key] 将是隐藏输入的值,0.

相关推荐

Can I make plugins required?

我正在开发自己的Wordpress主题,将用于多个客户端。它有一个主题选项页面,这样我每次都可以轻松自定义网站,但我也会在我制作的每个网站上使用一些插件(如SEO插件、安全性等)。有没有办法让它们成为“必需的”,这样我就可以得到这些插件的列表,这样当我在新网站上安装主题时就不必在插件目录中找到它们了?