UserMeta更改帖子ID的元值

时间:2016-03-08 作者:Brent

我正在构建一个专有的LMS(学习管理系统),并试图添加一个简单的书签功能,以保存$post->ID 在我的“课程”CPT(自定义帖子类型)中访问的最后一页。看起来这应该只是将当前页面的帖子id保存为用户的自定义元数据值,但毫无疑问update_user_meta() 函数保存为该“课程”CPT创建的层次结构中处于同一级别的帖子的帖子id。

代码如下:

function nb_course_post_actions(){

    global $current_user, $post;

    echo "I\'m about to give up! Post type is: {$post->post_type}.";
    if( $post->post_type === \'course\' ){
        $sid = $current_user->ID;
        $bookmark_id = $post->ID;
        print( $bookmark_id );

        if(  update_user_meta( $sid, \'course_bookmarks\', $bookmark_id ) === FALSE ){
            echo "Failed to update metadata";

        } else {
            echo "Metadata was updated: ";
            if ( get_user_meta($sid, \'course_bookmarks\', true ) !== $bookmark_id )
                wp_die(\'An error occurred\');
        }

    }
}

add_action( \'wp_footer\', \'nb_course_post_actions\' );
因此,假设会发生这样的情况:登录的用户访问课程CPT中的一个页面,在每个新页面加载时,记录当前帖子id的附加操作会添加到用户的元数据中,这样当用户离开并在稍后的日期回来时,他们可以单击一个链接,该链接将他们带到“课程”CPT中最后一次访问的页面。

问题是update_user_meta() 不可避免地会记录错误的post\\u id,该函数将转到wp_die() 每次运行。奇怪的是,当没有其他信息被发送或没有其他信息应该干扰所讨论的元数据时,它似乎有一些智能来保存与原始帖子相关的id,例如在同一级别分层嵌套的同一CPT的兄弟。meta\\u键“course\\u bookmark”在代码的其他任何地方都不存在。据我所知update_user_meta() 函数甚至不知道它正在保存一个POST id,因为它接收的唯一内容是一个数值。这可能是为了节省一些人的年龄或邮政编码,因为这些代码应该是已知的,它只是一个数字值,没有其他引用,这是一个帖子id。

它不应该知道这是一个post id,也不应该知道它与其他post\\u id有任何关系,这些post\\u id恰好是相同的CPT、相同的层次结构级别,并且是一个已发布的id,而不是修订。

我最初的功能要复杂得多,我在我的插件中把这段代码移到了所有地方,但我才意识到这个问题实际上似乎与wordpress的有关update_user_meta() 功能,而不是我调用它的位置或其他任何东西。将正确的ID发送给函数,但记录并返回了错误的ID(我在PHPMyAdmin中检查了记录的值)。但为什么呢?

UPDATE:

如果您按照这篇文章的评论和Pieter的建议进行操作,我会:

出于某种原因,这个bug似乎与<link rel=\'next\' href=\'path\\to\\next\\post\\\' /> WordPress在<head> html的节。我想这是为了帮助SEO。我没有在这个特定的网站上运行任何与SEO相关的插件,但我的代码(不太可能,因为我没有那么复杂)或我正在使用的主题(Kadence Themes的顶峰-顺便说一句,很好的主题)中有一些东西会获取这些信息,并通过$_GET 根据浏览器的网络监视器执行命令。作为临时解决方案,我将遵循this post by Hamergil 并将这段代码添加到我的LMS插件中:

add_filter( \'index_rel_link\', \'disable_stuff\' );
add_filter( \'parent_post_rel_link\', \'disable_stuff\' );
add_filter( \'start_post_rel_link\', \'disable_stuff\' );
add_filter( \'previous_post_rel_link\', \'disable_stuff\' );
add_filter( \'next_post_rel_link\', \'disable_stuff\' );

function disable_stuff( $data ) {
    return false;
}
不确定这是否是最好的解决方法,所以我仍然没有回答这个问题。

1 个回复
SO网友:Pieter Goosen

我相信你的问题与在你的单个帖子页面上获得正确的帖子对象有关。从你的问题中我发现$post 不包含所需的post对象。

你必须记住,$post 是WordPress用来存储当前post对象的非常糟糕的全局变量之一。在回路内部,$post 通常是相当可靠的,但在圈外,这是一场完全不同的球赛。问题是,$post 可以通过页面上的任何代码进行更改,甚至可以通过主循环进行更改。任何利用setup_postdata( $post )the_post() 设置$post 全局到循环中的当前帖子,所以$post 在任何给定的时间都可能会有所不同,这取决于您在页面上的位置。

忘记使用简单的wp_reset_postdata() 自定义查询后,循环将保留$post 到自定义查询中的最后一篇文章,而不是当前页面对象。这似乎是你所面临的问题,某种原因决定了$post 全局到当前页面对象以外的其他对象。

有多种方法可以更可靠地获取当前单个贴子页的对象。你可以看看my post here 并仔细阅读这个主题。因为功能如下query_posts 还中断了主查询对象,我最近开始使用$GLOBALS[\'wp_the_query\'] 哪种方法是获得正确数据的最可靠方法。

这里的另一个问题是,您在每次加载页面时都会运行它。仅仅检查post类型是不够的。记住,您使用$post 可以容纳任何post对象的全局。如果特定的post对象具有正确的post类型,那么无论您当前在哪个页面上,您的代码都将执行,因此我们必须检查是否在所需post类型的单个post页面上

让我们重写你的函数(淡化版),使其更可靠:(NOTE: 该代码未经测试,需要PHP 5.4+,此外,您始终可以通过使用Cookie在客户端存储数据来实现这一点,尽管这是一种不太可靠的方法

版本1如果您需要完整的post对象,这将是要使用的版本

/**
 * We can use the template_redirect hook here aswell. Change back to
 * wp_footer if this suits you better
 */ 
add_action( \'template_redirect\', \'nb_course_post_actions\' );
function nb_course_post_actions(){
    global $current_user;

    // Make sure we are on a singular course post type page, if not, bail
    if ( !is_singular( \'course\' )
        return;

    // Make sure we have a logged in user
    if ( !is_user_logged_in() )
        return; 

    // Great, we are on a single course post page and user is logged in, lets continue

    $post = sanitize_post( $GLOBALS[\'wp_the_query\']->get_queried_object() );

    $sid         = $current_user->ID;
    $bookmark_id = $post->ID;

    // Update the usermeta
    update_user_meta( $sid, \'course_bookmarks\', $bookmark_id );
}
如果您只需要post ID,而不需要其他信息,则为第2版

/**
 * We can use the template_redirect hook here aswell. Change back to
 * wp_footer if this suits you better
 */ 
add_action( \'template_redirect\', \'nb_course_post_actions\' );
function nb_course_post_actions(){
    global $current_user;

    // Make sure we are on a singular course post type page, if not, bail
    if ( !is_singular( \'course\' )
        return;

    // Make sure we have a logged in user
    if ( !is_user_logged_in() )
        return; 

    // Great, we are on a single course post page and user is logged in, lets continue

    $sid         = $current_user->ID;
    $bookmark_id = filter_var( $GLOBALS[\'wp_the_query\']->get_queried_object_id(), FILTER_VALIDATE_INT );

    // Update the usermeta
    update_user_meta( $sid, \'course_bookmarks\', $bookmark_id );
}

相关推荐

set a user-meta key as avatar

我有一个名为“meta kay”的用户;阿凡达;;此值包含用户上载的图像的URL。如何将此元值设置为用户化身?我使用此代码,但不工作add_filter( \'get_avatar\', \'slug_get_avatar\', 10, 5 ); function slug_get_avatar( $avatar, $id_or_email, $size, $default, $alt ) { //If is email, try and find user ID