WordPress常用的有两种钩子,过滤钩子add_filter和动作钩子add_action,它们是WordPress插件机制中非常重要的两个函数。

add_filter 过滤钩子用来创建一个过滤器,让其它的主题和插件对一个值进行修改过滤;

add_action 动作钩子核心代码跟过滤钩子差不多,但是没有返回值,单纯的就是在特定的地方执行插件或者主题开发者挂载的函数。

在开发WordPress博客同步到CSDN插件时,需要在WordPress发布文章后,加入一些动作钩子函数,实现同步发布到其它博客平台的功能,但同时又要避免修改文章后的重复发布。最早版本用的是publish_post和xmlrpc_public_post这两个函数,结合发布时间判断,实现了基本的功能;随后又加入了publish_future_post来支持晚于当前时间的定时发布功能,但对于将定时发布时间设在当前时间之前的,就没法同步了。为了解决这个问题,今天又查了一些资料,最后用transition_post_status替换了上面提到的几个钩子,完美实现了定时发布后的文章同步问题,值得记录一下。

首先需要了解的是动作钩子的用法和参数:

<?php  
     add_action( $tag, $function_to_add, $priority = 10, $accepted_args =1);  
?>  

$tag

是所挂载的动作钩子(action hooks)的名称,就是WordPress核心调用do_action()时一些可以触发的动作,用来确定挂载函数的位置,在官方Plugin API/Action ReferenceWordPress Hooks Database上可以查看动作钩子列表;$tag 也可以是一个主题或插件文件内部的一个动作,或者特定的标签“all”,这个函数将被所有的钩子调用。

$function_to_add

是你挂载的函数,用来实现期望添加的功能。

$priority

是可选项,用于指定和特定的动作相关联函数的执行顺序,数字越小,执行越早,默认值为10。

$accepted_args

也是可选项,用于标识挂钩函数所接受的参数数量,默认值为1。

 

然后为了便于了解下面那些发布文章时会被触发的钩子,先简单介绍下几个涉及到的属性值:

$post 为文章对象

$post_ID 为文章ID

$post_status 为文章对象的发布状态(包括new,publish,future,draft,pending,private,trash,auto-draft等)

$post_type 为文章对象的发布类型(包括post,page,attachment,revision等)

最后就是相关的动作钩子:

  1. publish_post:参数一个($post_ID),点击发布文章时就会被触发,仅含已发布;(推荐
  2. save_post:参数一个($post_ID),发布或更新文章时就会被触发,包含已发布、定时未发布;
  3. edit_post:参数两个($post_ID, $post),只要编辑已经存在的文章就会被触发;
  4. publish_future_post:参数一个($post_ID),到定时发布文章设定的时间点就会被触发,如果设定的时间早于发布时间,不会被触发;(推荐
  5. transition_post_status:参数三个($new_status, $old_status, $post),实现功能比较强大,可以根据文章发布状态的变化实现一些功能。
  6. {$old_status}_to_{$new_status}:参数一个($post),比如draft_to_publish是通常的文章发布事件,future_to_publish则可以用来处理定时文章发布事件。
  7. post_updated:参数三个($post_ID, $post_after, $post_before),已存在文章更新了就会被触发。类似内核函数 wp_update_post()

对比上面的函数说明可以发现,

post_updated事件是最强大的,可以获取到文章修改前后的所有内容,参数较多;类似内核函数 wp_update_post()

transition_post_status事件,功能也比较强;

{$old_status}_to_{$new_status}事件,针对性较强,可以对特定情况进行事件抓取;

publish_postsave_postedit_postpublish_future_post这四个事件就相对比较简单,可以视情况而用。

WordPress中有关发布、编辑文章的代码主要在文件/wp-includes/post.php里,主要函数有wp_update_post、wp_insert_post等,

有兴趣可以去细细看下源码或者官方网站上的相关文档,一定会收获不少的。

最后的最后,如果你也有同步文章的需求,记得去试下WP2CSDNBlog插件

目前已经支持同步CSDN、新浪和网易博客了,好用的话记得给个好评喔!

 

 

发布文章后,发送邮件示例

function post_published_notification( $ID, $post ) {
    $author = $post->post_author; /* Post author ID. */
    $name = get_the_author_meta( 'display_name', $author );
    $email = get_the_author_meta( 'user_email', $author );
    $title = $post->post_title;
    $permalink = get_permalink( $ID );
    $edit = get_edit_post_link( $ID, '' );
    $to[] = sprintf( '%s <%s>', $name, $email );
    $subject = sprintf( 'Published: %s', $title );
    $message = sprintf ('Congratulations, %s! Your article “%s” has been published.' . "\n\n", $name, $title );
    $message .= sprintf( 'View: %s', $permalink );
    $headers[] = '';
    wp_mail( $to, $subject, $message, $headers );
}
add_action( 'publish_post', 'post_published_notification', 10, 2 );

 

 

发布文章后,通知百度收录示例

// 百度百熊号(原创文章保护)
function post_baidu_xzh($ID, $post){
    global $wpdb;
    date_default_timezone_set('Asia/Shanghai');
    $post_date = $post['post_date'];
    $now_date = date("Y-m-d H:i:s");
    $old_date = date("Y-m-d H:i:s",strtotime("-3 day"));

    $urls_old = array(
        'https://blog.mimvp.com/sitemap-mimvp.xml',
        'https://blog.mimvp.com/sitemap_baidu.xml',
        'https://blog.mimvp.com/sitemap.html',
        'https://blog.mimvp.com/sitemap.xml',
        'https://blog.mimvp.com/index.php',
        'https://blog.mimvp.com/',
    );   
    $urls = array();
    $url = get_permalink($post->ID);
    array_push($urls, $url);

    $retry_status = false;
    $retry_NUM = 3;
    $retry_idx = 0;

    $api = 'http://data.zz.baidu.com/urls?appid=155736812345678&token=42gBbacdefgx&type=realtime';
    if($post_date < $old_date) {
        $api = 'http://data.zz.baidu.com/urls?appid=155736812345678&token=42gBbacdefgx&type=batch';
        $urls = array_merge($urls, $urls_old);
        $urls = array_unique($urls);
    }
    while($retry_status == false && $retry_idx < $retry_NUM) {
        $retry_idx += 1;
        $ch = curl_init();
        $options =  array(
            CURLOPT_URL => $api,
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POSTFIELDS => implode("\n", $urls),
            CURLOPT_HTTPHEADER => array('Content-Type: text/plain'),
        );   
        curl_setopt_array($ch, $options);
        $result = curl_exec($ch);
        $result_json = json_decode($result, true);
        $retry_status = $result_json["success_realtime"] == 1 ? true : false;
    }
    $result_json['retry_idx'] = $retry_idx;
    $result_json['post_date'] = $post_date;
    $result_json['now_date'] = $now_date;
    $result_json['old_date'] = $old_date;

    $from = "functions add_action";
    $xzhFilename = "/hello/mimvp-demo/post_baidu_xzh.txt";
    $xzhFile = fopen($xzhFilename, 'a') or die("unable to open file");
    fwrite($xzhFile, "\n\n\n===== $dtime -- from $from =====\n");
    fwrite($xzhFile, $url . "\n");
    fwrite($xzhFile, json_encode($result_json) . "\n");
    fclose($xzhFile);
}
#add_action('save_post', 'post_baidu_xzh2', 0);                  // 发布或更新文章时就会被触发
add_action('publish_post', 'post_baidu_xzh', 0);               // 点击发布文章时就会被触发
add_action('publish_future_post', 'post_baidu_xzh', 0);        // 到定时发布文章设定的时间点就会被触发

 

 

参考推荐

WordPress 开发一款自己的简单插件