laravel을 사용하는 프로젝트에서 schedule 처리는 Task Scheduling에 안내되어 있는 것처럼 \App\Console\Kernel
의 schedule(Schedule $schedule)
메서드 내에서 정의해서 사용한다.
laravel 기반 프로젝트에 추가한 package(module)에서 직접 schedule을 추가하고 싶다면 어떻게 해야 할까? 이 부분에 대해서는 메뉴얼 상에 안내된 내용이 없다. 하지만 "How to schedule Artisan commands in a package?" 글을 참고하면 아래와 같이 처리할 수 있다.
use Illuminate\Support\ServiceProvider;
use Illuminate\Console\Scheduling\Schedule;
class ScheduleServiceProvider extends ServiceProvider
{
public function boot()
{
$this->app->booted(function () {
$schedule = $this->app->make(Schedule::class);
$schedule->command('some:command')->everyMinute();
});
}
public function register()
{
}
}
Application Class의 booted($callback)
함수를 사용해서 schedule을 추가하는 것이다.
그런데 이 booted
함수가 lumen에서는 존재하지 않는다. booted
함수가 없는 것이 문제가 되는 이유는 schedule 개체를 만드는 Kernel Class의 defineConsoleSchedule()
메서드가 아래와 같이 구현되어 있으며 이 메서드는 Provider가 구성된 이후에 실행 되므로 $schedule
개체에 추가적인 schedule을 추가할 수 있는 진입 지점이 없다.
protected function defineConsoleSchedule()
{
$this->app->instance(
'Illuminate\Console\Scheduling\Schedule', $schedule = new Schedule($this->app[Cache::class])
);
$this->schedule($schedule);
}
따라서 lumen 프로젝트에서는 package 내부에서 직접적으로 schedule을 추가하는 것은 불가능해 보인다. 굳이 해야 한다면 Kernel 클래스의 defineConsoleSchedule()
메서드를 override 하여 아래와 같이 구현해야 한다.
protected function defineConsoleSchedule()
{
$this->app->instance(
'Illuminate\Console\Scheduling\Schedule', $schedule = ScheduleHelper::get()
);
$this->schedule($schedule);
}
new Schedule($this->app[Cache::class])
대신에 ScheduleHelper::get()
에서 인스턴스를 받아서 사용한다.
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Contracts\Cache\Repository as Cache;
class ScheduleHelper
{
/** @var Schedule */
private static $scheduleInstance = null;
/**
* @return Schedule
*/
static public function &get()
{
if (empty(static::$scheduleInstance)) {
static::$scheduleInstance = new Schedule(app(Cache::class));
}
return static::$scheduleInstance;
}
}
ScheduleHelper
에서는 schedule 인스턴스를 싱글톤으로 반환한다.
use Illuminate\Support\ServiceProvider;
use Illuminate\Console\Scheduling\Schedule;
class ScheduleServiceProvider extends ServiceProvider
{
public function boot()
{
$schedule = ScheduleHelper::get();
$schedule->command('some:command')->everyMinute();
}
public function register()
{
}
}
Provider 에서는 ScheduleHelper::get()
를 이용해서 schedule 인스턴스를 받아 schedule을 추가 한다.
위 방법은 lumen 프로젝트와 package 간의 종속 관계가 생기므로 권장할만한 방법은 아니다. 다만, 나의 경우는 lumen 프로젝트 개설시 기본적으로 직접 개발한 package를 사용하고 해당 package에서 기본 제어를 하도록 되어 있기 때문에 위 방법이 유용하게 사용될 수 있다(사실 대부분의 개발자들의 의견은 lumen은 간단한 프로젝트에서만 사용하고 다소 복잡해질 수 있는 프로젝트는 그냥 laravel을 쓰라는 것이다).