我正在构建一个专有的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;
}
不确定这是否是最好的解决方法,所以我仍然没有回答这个问题。
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 );
}