【发布时间】:2018-09-22 03:45:41
【问题描述】:
我有一个 WordPress 网站的客户,他不太懂技术,不想自己更新网站。网站上有一个页面将她自己的内容从她雇主的博客中联合起来。她雇主的网站没有 RSS 提要,但我可以使用 PHP Simple HTML DOM Parser 设置一个简单的脚本来抓取要联合的内容,并为她雇主网站上的每个新条目创建一个新的 WordPress 帖子。我每周执行一次 cron 任务,这与她为雇主网站编写新内容的频率一样。
我遇到的问题是,当我的 cron 脚本执行时间超过 30 秒时,WordPress 的 post_exists 函数无法找到我搜索的第一个条目,并创建了一个重复的帖子。
以下是 cron 脚本的代码。为了我客户的隐私,我将所有可识别信息替换为[[placeholder]]。
<?php
require( 'wp-load.php' );
if ( !function_exists( 'post_exists' ) ) {
require_once( ABSPATH . 'wp-admin/includes/post.php' );
}
require( 'simple_html_dom.php' );
update_bac();
function update_bac()
{
// log each cron execution for easier troubleshooting in the event of issues
$logfile = 'bac_cron.log';
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " \n", FILE_APPEND );
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " Cron executed\n", FILE_APPEND );
// Set a long time limit to avoid cron timeouts
$time_limit_success = (set_time_limit( 900 )) ? 'TRUE' : 'FALSE';
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " set_time_limit successful? {$time_limit_success} \n", FILE_APPEND );
这里删除的是执行实际抓取的代码。它工作,并构造了一个数组$entries_to_post,其中每个项目都是一个帖子数据数组,带有一个帖子标题('name'),一个“Y-m-d H:i:s”格式的发布日期('date'),雇主网站上帖子的链接 ('href') 和图片来源 ('img')。
// create a WordPress post for each entry in the array that doesn't already exist in the database
foreach( $entries_to_post as $postdata )
{
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " Looping entries_to_post, found {$postdata['name']}, {$postdata['date']} \n", FILE_APPEND );
$matching_post_id = post_exists( $postdata['name'], '', $postdata['date'] );
根据 WordPress 的文档,post_exists 应在命中时返回帖子 ID,如果不存在此类帖子,则返回 0。第一个参数是帖子标题,第二个参数是帖子内容(所有帖子都有空内容,因为我对所有相关数据都使用了自定义字段),第三个参数是发布日期。
if( $matching_post_id === 0 )
{
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " Match not found in database, adding new post... \n", FILE_APPEND );
$postarr = [
'post_author' => 0,
'post_date' => $postdata['date'],
'post_title' => $postdata['name'],
'post_status' => 'publish',
'post_type' => '[[custom-post-type]]'
];
$post_id = wp_insert_post( $postarr, true );
if( is_int( $post_id ) )
{
update_field( 'field_5741032e15daf', $postdata['href'], $post_id );
update_field( 'field_5b93201831b5d', $postdata['img'], $post_id );
update_field 是高级自定义字段功能;创建帖子后,我在这里使用它来更新必要的自定义字段。
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " Post created: " . $post_id . ", " . $postdata['name'] . ", " . $postdata['href'] . "\n", FILE_APPEND );
}
// wp_insert_post returns a WP_Error instead of a post ID if it fails
else if( is_wp_error( $post_id ) )
{
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " Something went wrong!\n", FILE_APPEND );
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " " . $post_id->get_error_message(), FILE_APPEND );
}
}
else
{
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " Matching post found with ID {$matching_post_id} \n", FILE_APPEND );
}
}
file_put_contents( $logfile, date( "Y-m-d H:i:s" ) . " Reached end of array\n", FILE_APPEND );
}
如果 cron 执行时间少于 30 秒,则它按预期工作,如果没有新条目,则日志文件如下所示:
2018-09-21 17:36:03
2018-09-21 17:36:03 Cron executed
2018-09-21 17:36:03 set_time_limit successful? TRUE
2018-09-21 17:36:24 Looping entries_to_post, found [[post-title-1]], 2018-06-08 00:00:00
2018-09-21 17:36:24 Matching post found with ID 516
2018-09-21 17:36:24 Looping entries_to_post, found [[post-title-2]], 2018-07-12 00:00:00
2018-09-21 17:36:24 Matching post found with ID 475
2018-09-21 17:36:24 Looping entries_to_post, found [[post-title-3]], 2018-08-31 00:00:00
2018-09-21 17:36:24 Matching post found with ID 476
2018-09-21 17:36:24 Looping entries_to_post, found [[post-title-4]], 2018-08-17 00:00:00
2018-09-21 17:36:24 Matching post found with ID 477
2018-09-21 17:36:24 Looping entries_to_post, found [[post-title-5]], 2018-09-07 00:00:00
2018-09-21 17:36:24 Matching post found with ID 478
...
2018-09-21 17:36:24 Reached end of array
如果执行时间超过 30 秒,则日志如下所示:
2018-09-21 16:53:27
2018-09-21 16:53:27 Cron executed
2018-09-21 16:53:27 set_time_limit successful? TRUE
2018-09-21 16:54:27
2018-09-21 16:54:27 Cron executed
2018-09-21 16:54:27 set_time_limit successful? TRUE
2018-09-21 16:55:01 Looping entries_to_post, found [[post-title-1]], 2018-06-08 00:00:00
2018-09-21 16:55:01 Matching post found with ID 516
2018-09-21 16:55:01 Looping entries_to_post, found [[post-title-2]], 2018-07-12 00:00:00
2018-09-21 16:55:01 Matching post found with ID 475
2018-09-21 16:55:01 Looping entries_to_post, found [[post-title-3]], 2018-08-31 00:00:00
2018-09-21 16:55:01 Matching post found with ID 476
2018-09-21 16:55:01 Looping entries_to_post, found [[post-title-4]], 2018-08-17 00:00:00
2018-09-21 16:55:01 Matching post found with ID 477
2018-09-21 16:55:01 Looping entries_to_post, found [[post-title-5]], 2018-09-07 00:00:00
2018-09-21 16:55:01 Matching post found with ID 478
...
2018-09-21 16:55:01 Reached end of array
2018-09-21 16:55:02 Looping entries_to_post, found [[post-title-1]], 2018-06-08 00:00:00
2018-09-21 16:55:02 Match not found in database, adding new post...
2018-09-21 16:55:02 Post created: 526, [[post-title-1]], [[href]]
2018-09-21 16:55:02 Looping entries_to_post, found [[post-title-2]], 2018-07-12 00:00:00
2018-09-21 16:55:02 Matching post found with ID 475
2018-09-21 16:55:02 Looping entries_to_post, found [[post-title-3]], 2018-08-31 00:00:00
2018-09-21 16:55:02 Matching post found with ID 476
2018-09-21 16:55:02 Looping entries_to_post, found [[post-title-4]], 2018-08-17 00:00:00
2018-09-21 16:55:02 Matching post found with ID 477
2018-09-21 16:55:02 Looping entries_to_post, found [[post-title-5]], 2018-09-07 00:00:00
2018-09-21 16:55:02 Matching post found with ID 478
...
2018-09-21 16:55:02 Reached end of array
...s 只是一堆额外的循环迭代,总共大约 40 次——为简洁起见,我截断了日志。
如您所见,如果时间超过 30 秒,则 cron 会执行两次。第二次执行恰好在第一次执行后一分钟发生,但由于某种原因,它在第二次执行时立即循环遍历数组两次,并且在其中一个循环(有时是第一个循环,有时是第二个循环)中,第一项没有找到 post_exists 的数组,并创建了一个重复的帖子。
我尝试过的事情:
我将
if( !post_exists(...) )更改为if( post_exists(...) === 0 )以确保我实际上得到的是 0 而不是别的东西。没有效果。我在脚本顶部添加了
set_time_limit( 900 )(并记录了它以确保它有效)以确保 cron 脚本有足够的时间执行。我添加了一个带有
max_execution_time = 120和error_log = /home/[[user]]/html/php_error.log的.user.ini。我希望增加全局的最大执行时间可能会有所帮助,以防它是post_exists函数或其他超时的东西,但它似乎没有任何效果。 (客户端使用 GoDaddy 的托管 WordPress 计划,因此我的服务器配置和访问选项有点受限。.user.ini 文件是 GoDaddy 所说的进行 PHP 配置的方式,它应该每 5 分钟检查一次文件.)我添加了更多日志语句以查看到底发生了什么,这帮助我缩小了问题的范围,但我仍然不知道如何实际解决它。
【问题讨论】: