将自定义方法添加到 Laravel 5 调度程序

Adding custom methods to Laravel 5 scheduler

我想知道将周末之类的事情添加到可用时间表限制的最佳方式是什么:

Illuminate\Console\Scheduling\Event.php
public function weekdays()
{
    return $this->spliceIntoPosition(5, '1-5');
}

及其逻辑对立面:

public function weekends()
{
        return $this->days(array( '0','6'));
}

我应该在哪里包含这些东西,以免它们被框架更新覆盖?

首先,如果你只缺少 weekends() 方法,你可以通过调用 days(6,7) 在你的活动中。

如果您需要向调度程序添加更多逻辑,请继续阅读。

我查看了代码,虽然 Laravel 没有提供扩展 Scheduler 的方法,特别是其预定的 Events ,使用其他方法,仍然可以从 Kernel::schedule().

应用其他约束

根据您的需要,有两种方法。

  1. 如果你想为一个事件设置一些自定义的 CRON 表达式,你可以简单地使用它的 cron() 方法:

    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            //scheduled code
        })->cron('0 1 2 * * *')->daily();
    }
    
  2. 如果您需要使用现有方法应用一些 CRON 约束,但以后需要按照 weekdays() 使用 的方式进行修改spliceIntoPosition,可以通过调用getExpression()访问,修改,然后使用cron().

    protected function schedule(Schedule $schedule)
    {
        $event = $schedule->call(function () {
            //scheduled code
        });
    
        $scheduledAt = $event->getExpression(); //get cron expression
    
        ...; //modify the $scheduledAt expression
    
        $event->cron($scheduledAt); // set the new schedule for that even
    }
    

如果您想为多个事件重用逻辑,可以在 Kernel.php 中添加辅助函数,例如:

    protected function specialSchedule(\Illuminate\Console\Scheduling\Event $event) {
      $scheduledAt = $event->getExpression();

      ...; // modify $scheduledAt expression

      $event->cron($scheduledAt);

      return $event;
    }

然后您可以在定义时间表时重用该逻辑:

    protected function schedule(Schedule $schedule)
    {
        $this->specialSchedule($schedule->call(function () {
            //scheduled code
        }));
    }

更新:

还有另一种方法可以做到这一点 - 有点复杂,因为它需要您提供自己的日程安排和事件 classes,但也更灵活。

首先,实现您自己的事件 class 并添加新方法:

    class CustomEvent extends \Illuminate\Console\Scheduling\CallbackEvent {
      public function weekends() {
        return $this->days(6,7);
      }
    }

然后是您自己的 Schedule class,以便它创建 CustomEvent 个对象:

    class CustomSchedule extends \Illuminate\Console\Scheduling\Schedule 
    {
      public function call($callback, array $parameters = [])
      {
        $this->events[] = $event = new CustomEvent($callback, $parameters);

         return $event;
      }

      public function exec($command, array $parameters = [])
      {
        if (count($parameters)) {
          $command .= ' '.$this->compileParameters($parameters);
        }

        $this->events[] = $event = new Event($command);

        return $event;
      }
   }

最后,在您的 Kernel.php 中,您还需要确保您的新时间表 class 用于安排:

    protected function defineConsoleSchedule()
    {
      $this->app->instance(
        'Illuminate\Console\Scheduling\Schedule', $schedule = new Schedule
      );

      $this->schedule($schedule);
    }

根据@jedrzej.kurylo的回答,我在laravel 5.8:

做了这个

php artisan make:model CustomCallbackEvent

php artisan make:model CustomEvent

php artisan make:model CustomSchedule

在 CustomCallbackEvent 中:

use Illuminate\Console\Scheduling\CallbackEvent;
use Illuminate\Console\Scheduling\EventMutex;

class CustomCallbackEvent extends CallbackEvent
{
    public function __construct(EventMutex $mutex, $callback, array $parameters = [])
    {
        parent::__construct($mutex, $callback, $parameters);
    }
}

在自定义计划中:

use Illuminate\Console\Scheduling\Schedule;

class CustomSchedule extends Schedule
{
    public function call($callback, array $parameters = [])
    {
        $this->events[] = $event = new CustomCallbackEvent(
            $this->eventMutex,
            $callback,
            $parameters
        );

        return $event;
    }

    public function exec($command, array $parameters = [])
    {
        if (count($parameters)) {
            $command .= ' '.$this->compileParameters($parameters);
        }

        $this->events[] = $event = new CustomEvent($this->eventMutex, $command, $this->timezone);

        return $event;
    }
}

在自定义事件中:

use Illuminate\Console\Scheduling\Event;

class CustomEvent extends Event
{
    public function myFunction()
    {
        //your logic here
    }
}

在Kernel.php中:

protected function defineConsoleSchedule()
    {
      $this->app->instance(
        'Illuminate\Console\Scheduling\Schedule', $schedule = new CustomSchedule
      );

      $this->schedule($schedule);
    }