【问题标题】:Wordpress - How to schedule function to run every 48 hoursWordpress - 如何安排功能每 48 小时运行一次
【发布时间】:2019-06-29 15:37:26
【问题描述】:

我的数据库中保存了一系列报价,我希望每 48 小时从数据库中提取一个单一的随机报价并在我的网站上显示一次。

我找到了使用自定义 cron 计划事件每 48 小时安排一次的代码。但是,我假设我执行不正确,因为虽然网站上显示了一个随机引用,但每次刷新页面时它都会切换到一个新的随机引用,而不是每 48 小时一次。

function quote_custom_cron_schedule( $schedules ) {
$schedules['every_two_days'] = array(
    'interval' => 172800, // Every 48 hours
    'display'  => __( 'Every 48 hours' ),
);
return $schedules;
}
add_filter( 'cron_schedules', 'quote_custom_cron_schedule' );

//Schedule an action if it's not already scheduled
if ( ! wp_next_scheduled( 'quote_cron_hook' ) ) {
wp_schedule_event( time(), 'every_two_days', 'quotes_cron_hook' );
}

//Hook into that action that'll fire every 48 hours
 add_action( 'quotes_cron_hook', 'quotes_cron_function' );

//Function that executes via cron
function quotes_cron_function() {
$args = array(
'post_type' => 'quote',
'orderby' => 'rand',
'posts_per_page'=> 1,
);

  $quotes = new WP_Query( $args );
  $quotes_output = '';

  if( $quotes->have_posts() ):
    while ( $quotes->have_posts() ) : $quotes->the_post();
      $quotes_title = get_the_title();
      $quotes_content = get_the_content();
      $quotes_output .= '<div id="quote"><p>&quot;' . $quotes_content . '&quot;</p><p class="quote-name">' . $quotes_title . '</p></div>';
    endwhile;
  else:
      $quotes_output = '';
  endif;

  wp_reset_postdata();
  echo $quotes_output;
}

然后我的 header.php 文件中有以下内容:

<?php do_action( 'quotes_cron_hook' ); ?>

这是在执行函数,但是每次刷新页面时都会执行。我需要该功能等待 48 小时才能再次更改报价。我觉得我可能在这里遗漏了一些简单的东西。

【问题讨论】:

  • wp 调度程序只能在活动请求发生时运行,因此 wp 调度程序只能授予作业在给定时间之前不会运行的权限。没有被授权者会在之后的特定时间运行,它会在分配的时间之后的下一个请求上运行。
  • 请注意,WordPress cron 作业实际上并不是 cron 作业。每当有人访问触发您的脚本的页面时,WordPress 将检查该 cron 作业是否已在计划的窗口内运行。如果不是,那么它将运行,否则将被忽略。它将不会自动触发。让它自动运行的唯一方法是 1)在服务器上设置一个实际的 cron 作业(可能对您来说不可能),或者 2)创建一个单独的服务,旨在为您定期访问该页面(您最好的选择)强制 WordPress cron 作业运行。
  • @B.Fleming - 我忘了向该站点发出请求,这是我应该记住的实际事情,我正在制作一个几乎需要使用 CRON 的 wordpress 插件,但要设置它对于插件用户来说有点困难。所以这是我可以添加到我的网站的服务。 ... :-)

标签: php wordpress loops cron schedule


【解决方案1】:

你的问题很可能是这样的:

if ( ! wp_next_scheduled( 'quote_cron_hook' ) ) {
    wp_schedule_event( time(), 'every_two_days', 'quotes_cron_hook' );
}

你有quote_cron_hookquotes_cron_hook 有一个s 没有。这种不匹配将导致条件永远不会失败,因为事件命名错误,它永远不会被安排,并且这个条件会传递给每个单独的请求。依次运行wp_schedule_event 函数,开始时间为time(见下文)。

如果您查看以下wp_schedule_event 链接的文档。 time() 的第一个参数是这个

$timestamp(整数)(必需)您希望事件发生的第一次。这必须是 UNIX 时间戳格式。 WP cron 使用 UTC/GMT 时间,而不是本地时间。使用 time(),它在 WordPress 中始终是 GMT。

请注意您希望事件发生的第一次,现在是time(),因为它的命名错误,它会在每次页面加载时执行此操作,然后立即运行。

您当然可以将time() 设置为其他值,但这只会掩盖问题。

其他东西

这也可能是错误的。

  wp_schedule_event( time(), 'every_two_days', 'quotes_cron_hook' );

更具体地说,查看文档

https://codex.wordpress.org/Function_Reference/wp_schedule_event

$recurrence(字符串)(必需)事件应该多久重复一次。有效值:

  • 每小时
  • 每天两次
  • 每天

默认:无

我没有看到 every_two_days 在那里,除非它没有记录。老实说,我没有太多使用 WP 调度程序。 Default: None 可能是您在此处实际拥有的,因为 WP 无法识别该值,因此它回退到无。但我不确定那到底是什么。

更多其他内容

正如我在 cmets 中所说的(这可能适合您使用,但请记住)

wp 调度程序只能在活动请求发生时运行,因此 wp 调度程序只能允许作业在给定时间之前不会运行。没有被授权者会在之后的特定时间运行,它会在分配的时间后的下一个请求上运行

将此添加到 wp-config.php

 define('DISABLE_WP_CRON', true);

禁用内置的 cron/scheduler。然后进入 C-Panel 或编辑 crontab (crontab -e) 并添加此 cron 作业以每分钟运行一次(或某个有用的时间间隔)

 php -q pathtowp/wp-cron.php

这是做什么的,它将调度时间的控制从 wordpress 中移开,并将其交给“实际的”CRON 应用程序(在 linux 上)。这样它就不会依赖页面加载。

但是,正如我所说,因为这是一个应该有人查看的帖子,所以正常的 WP 行为可能对你来说完全没问题。一般来说,如果我对调度程序做任何事情,我只依赖真正的 CRON,这就是我提到它的原因。

希望对你有帮助!

【讨论】:

    【解决方案2】:

    我认为你的想法是错误的。您的标题中有do_action( 'quotes_cron_hook' ),它将在每次页面加载时触发quotes_cron_hook 操作,然后允许quotes_cron_function() 在每次触发时挂钩该操作。这似乎与您报告的行为一致。

    问题是,设置 WP cron 作业不会强制钩子在该特定时间间隔运行。在您的情况下,每次页面加载时都会触发 quotes_cron_hook 操作,但它也会每 48 小时触发一次。

    在我看来,您想要的功能是提取“临时”报价,然后每 48 小时更改一次。为此,您需要以下内容:

    if ( ! wp_next_scheduled( 'change_quote_hook' ) ) {
        wp_schedule_event( time(), 'every_two_days', 'change_quote_hook' );
    }
    
    add_action( 'change_quote_hook', 'change_quote_function' );
    
    function change_quote_function() {
          $args = array(
              'post_type' => 'quote',
              'orderby' => 'rand',
              'posts_per_page'=> 1,
          );
    
          $quotes = new WP_Query( $args );
          $quotes_output = '';
    
          if( $quotes->have_posts() ):
              while ( $quotes->have_posts() ) :
                  $quotes->the_post();
                  // Set the temporary post using a WordPress option
                  update_option( 'quote_post', get_the_ID() );
              endwhile;
          endif;
    
          wp_reset_postdata();
    }
    

    然后,cron 作业将每 48 小时触发一次此功能(或多或少正如人们所指出的那样),并将报价设置在可以显示的位置。然后,您的标题可以执行每次页面加载时显示报价的操作。

    add_action( 'display_quote', 'display_quote_function' );
    function display_quote_function() {
        // Get the quote post ID
        // The default, 1, will be returned if the option is not set
        $quote_id = get_option( 'quote_post', 1 );
    
        $quote = get_post( $quote_id ); 
        $quotes_title = quote->post_title;
        $quotes_content = quote->post_content;
        $quotes_output = '<div id="quote"><p>&quot;' . $quotes_content . '&quot;</p><p class="quote-name">' . $quotes_title . '</p></div>';
        echo $quotes_output;
    }
    
    do_action('display_quote');
    

    【讨论】:

    • 好的。我理解你的逻辑,而且它似乎确实可行。但是,我仍然不太确定在 change_quote_function 中设置值然后在 display_quote_function 中检索的正确方法。我会按照我已经这样做的方式将它们保存为普通变量吗?或者我会使用一些特定的方法。而且我假设我仍然会在标题中运行 do_action('display_quote')?
    • 我会使用全局变量吗?另外,第一次设置报价(它的初始状态)是什么?
    • @jasonTakesManhattan 一种选择是将帖子 ID 存储在 WordPress 选项中。我编辑了我的答案以这样做。您也可以通过这种方式指定默认报价。如果您像我在示例中那样使用帖子 ID,则默认值应该是默认报价的帖子 ID。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 1970-01-01
    • 2014-02-08
    • 2018-02-05
    相关资源
    最近更新 更多