为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没有提供扩展调度程序的方法,特别是它的调度事件,使用其他方法,仍然可以从Kernel::schedule()应用额外的约束。

根据您的需要,有两种方法可以做到这一点。

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

    protected function schedule(Schedule $schedule)
    {
        $schedule->call(function () {
            //scheduled code
        })->cron('0 1 2 * * *')->daily();
    }
    
  2. 如果您需要使用现有方法应用一些CRON约束,但需要稍后修改它的方式weekdays()使用 spliceintopposition ,您可以通过调用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
        }));
    }

更新:

还有一种方法可以做到这一点——有点复杂,因为它需要您提供自己的Schedule和Event类,但也更灵活。

首先,实现您自己的Event类并在其中添加新方法:

    class CustomEvent extends 'Illuminate'Console'Scheduling'CallbackEvent {
      public function weekends() {
        return $this->days(6,7);
      }
    }
然后是你自己的Schedule类,这样它就创建了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中,您还需要确保您的新调度类用于调度:

    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);
    }
}
在CustomSchedule:

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;
    }
}
在CustomEvent:

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);
    }

Illuminate'Console'Scheduling'Event类使用Macroable特性。这意味着您可以在不继承类的情况下动态地向类添加方法。

首先你必须在boot方法中注册它:

use Illuminate'Console'Scheduling'Event;
use Illuminate'Support'ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
    public function boot()
    {
        Event::macro(
            'weekends',
            function () {
                /** @var Event $this */
                return $this->days([0, 6]);
            }
        );
    }
}

然后你可以像使用其他方法一样使用它:

$schedule->command('do-work')->weekends();

有关宏的详细信息,请参见https://asklagbox.com/blog/laravel-macros