#1 楼
从WordPress版本3.7开始。 -IIRC-save_post
钩子-有关钩子及其用法的更多信息,请参见代码参考:save_post
和Codex:save_post
-具有第三个参数$update
,可用于确定该参数。@param整型int $ post_ID帖子ID。
@param WP_Post帖子$ post帖子对象。
@param bool不管此帖子是否已更新。
注意:
$update
并不总是true
–您可以使用以下代码亲自对其进行测试。但是,它没有很好的文档记录,可能远没有最佳命名,因此会产生误导性的期望。下面的代码可用于某些调试,并尝试何时拦截代码执行,因为否则您将看不到信息/消息。我认为,欺骗性行为的罪魁祸首是对修订和自动保存的处理-可以将其禁用,但我不建议这样做,也没有对其进行测试。不知道这是否需要一张Trac票,所以我没有打开那张票,如果您这么想,请按照链接自行完成。除此之外,如评论中所述,如果您有特定问题,请发布新问题。add_action( 'save_post', 'debug_save_post_update', 10, 3 );
function debug_save_post_update( $ID, $post, $update ) {
echo '<pre>';
print_r( $post ); echo '<br>';
echo '$update == ';
echo $update ? 'true' : 'false';
//conditions
if( ! $update && $post->post_status == "auto-draft" ) {
// applies to new post
echo ' && $post->post_status == "auto-draft"';
//die();
} else if ( ! $update ) {
// applies basically to the (auto saved) revision
//die();
} else {
// applies to updating a published post
// when there is a revision, which is normally the case,
// standard behavior of WordPress, then it is considered
// an update, which is where the confusion sets in
// there are other methods, like checking time or post status
// depending on your use case it might be more appropriate
// to use one of those alternatives
//die();
}
echo '</pre>';
//die();
}
评论
$ update参数即使是新帖子也始终为true。所以这个参数没用。不确定它是否曾经奏效,但可以肯定的是,它并没有按照最新版本的wordpress 4.8所记录的那样工作。
–所罗门·克洛森(Solomon Closson)
17年7月20日在20:32
@SolomonClosson如果您看看wp_publish_post,那么可以。但这在wp_insert_post中的用法并不正确。我编写了一个调试功能,将其添加到答案中。
–尼古拉
17年7月21日在0:11
@SolomonClosson如果您遇到实际的具体问题,请提出一个新问题。查看有关调试功能的修订说明。
–尼古拉
17年7月21日在0:34
save_post挂钩具有第三个参数,该参数始终设置为TRUE,因此不确定与其他挂钩有什么关系,而不是其他挂钩。我说的是你答案中的陷阱。这是不正确的。
–所罗门·克洛森(Solomon Closson)
17年7月23日在23:42
@SolomonClosson正如我所说的,挂钩发生了两次:wp_insert_post(),wp_publish_post()。后者只是将来的帖子,其中$ update设置为true。否则,对于wp_insert_post(),$ update并不总是true。
–尼古拉
17年7月24日在13:08
#2 楼
我执行此检查的方法(在带钩子的函数内)是比较发布日期和修改日期(在格林威治标准时间进行标准化)function check_new_vs_update( $post_id ){
$myPost = get_post($post_id);
$post_created = new DateTime( $myPost->post_date_gmt );
$post_modified = new DateTime( $myPost->post_modified_gmt );
$diff = $created->diff( $modified );
$seconds_difference = ((($diff->y * 365.25 + $diff->m * 30 + $diff->d) * 24 + $diff->h) * 60 + $diff->i)*60 + $diff->s;
if( $seconds_difference <= 1 ){
// New post
}else{
// Updated post
}
}
add_action('save_post', 'check_new_vs_update' );
之所以可行,是因为即使在创建时,该帖子也具有“修改”日期附加到它,与“创建”日期完全相同,但是我们允许任一种方式都以1秒为单位的差异,以防在创建信息期间出现一秒的滴答声。
评论
有时post_date_gmt是2019-03-12 01:31:30而post_modified_gmt是2019-03-12 01:31:31。 :(
–何一非何一非
19年3月12日在4:06
@HeYifei何一非好点,如果处理在给定的秒数结束时开始,则可能会发生这种情况。我已经更新了答案,谢谢
–詹姆斯·库欣
19年3月12日在13:04
伙计们,只是一个信息。在还原和删除帖子时会触发该挂钩。
–梅尔文
19年5月9日,11:39
很高兴认识@melvin,谢谢
–詹姆斯·库欣
20/08/17在17:43
我不敢相信它是如此复杂。 WordPress永远不会令我惊讶。
–amarinediary
1月4日13:29
#3 楼
我最终只是在设置前检查自定义值的存在。这样,如果它是新创建的帖子,则自定义值将不存在。function attributes_save_postdata($post_id) {
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
if (!wp_verify_nonce($_POST['_attributes_noncename'], plugin_basename(__FILE__))) return;
if ('page' == $_POST['post_type']) {
if (!current_user_can('edit_page', $post_id)) return;
} else {
if (!current_user_can('edit_post', $post_id)) return;
}
$termid = get_post_meta($post_id, '_termid', true);
if ($termid != '') {
// it's a new record
$termid = 'update';
} else {
// it's an existing record
}
update_post_meta($post_id, '_termid', $termid);
}
add_action('save_post', 'attributes_save_postdata');
评论
为此,您是否必须首先使用add_post_meta创建自定义字段?
–MF1
2013年4月9日在2:03
根据食典:[update_post_meta]可以代替add_post_meta()函数使用。 codex.wordpress.org/Function_Reference/update_post_meta
–这里是什么
2014年1月20日在21:46
如果帖子是在通过插件激活启用代码挂钩之前创建的,则这可能会失败。较旧的帖子没有元集,因此对它们的第一次更新将被视为新的。
– Vasu Chawla
18年5月5日在19:13
@VasuChawla,因此在这种情况下,检查该特定元术语的存在isset()(例如)而不是检查其真假,可能更可靠。作为第三个条件。 (如果,否则,...否则)
– ViktorBorítás
20年8月1日在17:03
#4 楼
带有“更新”参数的elocin答案示例:function save_func($ID, $post,$update) {
if($update == false) {
// do something if its first time publish
} else {
// Do something if its update
}
}
add_action( 'save_post', 'save_func', 10, 3 );
评论
更好的方法是将更新块放在第一位,只允许执行if($ update)或将新块放在第一位,但要使用if(!$ update)。后者将使OP成为更好的实践,并且在三元运算符之类的情况下,WordPress编码标准会优先于您的方法使用OP
–詹姆斯·库欣
16年11月17日在11:38
#5 楼
您可以将pre_post_update操作挂钩用于更新代码,将save_post用于新的邮政编码。它可以在帖子更新之前起作用。评论
创建和更新帖子时都会触发save_post挂钩(在WordPress将其保存到数据库之后)。更新帖子时但在更新帖子之前会触发pre_post_update-这可能很重要。
–斯蒂芬·哈里斯(Stephen Harris)
2012年8月12日18:59
#6 楼
正如Darshan Thanki所暗示的(斯蒂芬·哈里斯(Stephen Harris)进一步阐述)一样,您可以使用pre_post_update
来发挥自己的优势。 PHP(令人震惊...),因此将该变量拉入函数范围不起作用-因此是全局的。请注意,这实际上只能在
function is_new_post() use ( &$new_post )
事件中/之后可靠地使用(通常就足够了,至少对于我们正在使用它进行操作。)#7 楼
触发save_post时,有关该帖子的所有信息都已可用,因此从理论上讲,您可以使用function f4553265_check_post() {
if (!get_posts($post_id)) {
// if this is a new post get_posts($post_id) should return null
} else {
// $post_id already exists on the database
}
}
add_action('save_post','f4553265_check_post');
,但这未经测试。 =)
评论
当您到达save_post时,帖子本身已经保存到数据库中-因此get_posts将返回当前帖子。
–斯蒂芬·哈里斯(Stephen Harris)
2012年4月12日在18:25
是的,只需在食典中检查一下即可。感谢您的单挑。
– moraleida
2012年4月12日在18:59
这不适用于get_posts,但适用于get_post。
–加文
20年8月18日在2:28
#8 楼
使用内置函数且不添加数据库的另一种方法涉及get_post_status()
。$post_status = get_post_status();
if ( $post_status != 'draft' ) {
//draft
} else {
//not a draft: can be published, pending, etc.
}
但是请注意,如果您打算稍后进行设置,则可能不合适状态恢复为“草稿” –下一次更新帖子时,将重复您的说明。
根据上下文,您可能需要考虑
get_post_status()
可以返回的各种字符串,以构建更合适的字符串场景。请参见Codex以获得get_post_status()和发布状态
可能的值为: -已发布的帖子或页面
'待定'-待审核的帖子
'草稿'-处于草稿状态的帖子
'自动草稿'-新建的帖子,没有内容
'future'-将来要发布的帖子
'private'-未登录的用户不可见
'inherit'-修订版。请参见get_children。
'trash'-帖子在回收站中。已在2.9版中添加。
评论
我不认为这能达到要求。如果我创建一个新帖子,然后单击“发布”,则将首次执行save_post(),但在执行此过程中,get_post_status()已经返回“发布”而不是“草稿”,即使它只是在正在发布。
– cgogolin
17年11月25日在18:39
#9 楼
我刚刚遇到了关于新的和更新的save_post
。阅读完源代码后即可了解流程。我发现以下方法可能有用。由于之前尚未提及。查看它是否对任何人有用。 (测试是Core 5.3.3)创建帖子的流程大致如下:
按Add New(Post)
$ post = get_default_post_to_edit($ post_type,true);将在
get_default_post_to_edit()接收参数$ create_in_db = true
的地方被调用,因此将立即调用wp_insert_post(),并创建
auto-draft
帖子,即使它没有保存,每次单击Add New
时,都会显示auto-draft
创建的$ update对于发布始终为true。因此,当发布新帖子时,它是正确的。
通过比较$ _POST对象用于新帖子和更新帖子或重新发布帖子,最主要的区别是值
_wp_http_referer
,新帖子是/wp-admin/post-new.php
假设:假设帖子是通过UI发布/添加的。如果通过其他机制,自定义代码完成,则需要进行检查以进行调整。
add_action( 'save_post', 'test_save_post_check', 0, 3 );
function test_save_post_check( $post_ID, $post, $update ) {
// other tests + this
// checking the 'post-new' position from the '_wp_http_referer'
if( strpos( wp_get_raw_referer(), 'post-new' ) > 0 ) {
// new
} else {
// update
}
}
#10 楼
由于$update
参数没有用,因此这是我测试的最快方法: function wpse48678_check_is_post_new($post_id, $post, $update)
{
if (false !== strpos($_POST['_wp_http_referer'], 'post-new.php')) {
return true; // Or do something else.
} else {
return false; // Or do something else.
}
}
add_action('save_post_{$post_type}', 'wpse48678_check_is_post_new', 10, 3);
评论
我认为这是不可能的。请参阅下面@moraleida的回答我的评论。为什么您需要知道这是新帖子还是正在更新?可能有解决方法或替代方法。